OmniAICreator/Qiita-1.07M huggingface dataset:
Laravel8 マイページを見られるユーザーを限定する（アクセス制限）

## やりたいこと
- マイページを自分（特定のユーザー）以外がアクセスできないようにしたい。
- 未ログイン状態からのアクセスがあればログイン画面にリダイレクトしたい。
- ログイン済みであっても他人のマイページは閲覧できないようにしたい。

## 環境
PHP7
Laravel8

## 前提
1. マイページそのものは作成しておく
1. マイページのURLにパラメータとしてユーザーIDが表示される状態になっている

### コントローラー

コントローラーでは、if文を使ってパラメーターに入るユーザーIDとアクセスしようとしているユーザーのユーザーIDが一致しないと閲覧できないようにした。

```PHP:app/Http/Controllers/RecordUsersController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use App\Models\Record;
use App\Models\User;
use Illuminate\Support\Facades\DB;

class RecordUsersController extends Controller
{
    //
   public function show_by_user($id)
    {
        $user = Auth::user();
        $id = Auth::id();

        $user = User::find($id); 
        $records = Record::where('user_id',$user->id)->sortable()->get(); 


        if($user->id == $id){

        return view('record.showbyuser', [
            'user_name' => $user->name, 
            'records' => $records, 
        ]);
        }else{
            return redirect('/login');
        }

    }
}
```

### ルーティング

ルーティングでは`->middleware('auth')`を追記して、未ログイン状態からアクセスするとログインを要求するように変更。

```PHP:routes/web.php
use App\Http\Controllers\RecordUsersController;
// ユーザー投稿の一覧表示画面
Route::get('/record/user/{user_id}', [RecordUsersController::class, 'show_by_user'])->name('show_by_user_record')->middleware('auth');
```

## できたこと
- マイページを自分（特定のユーザー）以外がアクセスできないようになった。
- 未ログイン状態からのアクセスがあればログイン画面にリダイレクトするようになった。
- ログイン済みであっても他人のマイページは閲覧できないようになった。

## うまくいっていないこと

URLパラメーターに入るユーザーIDがアクセスしようとするユーザーIDと一致しないときにエラー文を表示したり、別ページにリダイレクトさせようとしたができなかった。if~else..の記述に問題があると思われるが、現状原因不明のまま。今後改善したい。
# 使い終わった壁紙を自動で削除したい！

# 使い終わった壁紙を自動で削除したい！
「東京ディズニーリゾートの壁紙を毎月自動でダウンロード・設定するプログラムを作った！」と友人に話をしたところ、「昔の壁紙は消えないの？？」と聞かれました。
私は何かと記念に残しがちですが、よくよく考えれば確かに要らない気がするので、ダウンロードするタイミングで削除しちゃおうと思います。

前回の記事はこちら↓

https://qiita.com/ayk_f/items/40eca2f7376a2b04ce4c

# ざっくりフローチャート
前回の記事で、「今月の壁紙が指定フォルダに格納されていない場合、壁紙をダウンロードする。」という条件分岐を追加したので、壁紙をダウンロードする処理の前に、古い壁紙を削除する処理（オレンジ部分）を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1953283/b9c7522e-a36d-f0a4-3fad-dcf2d24c91ac.png)


# 削除対象ファイルのリストアップ
まずは削除対象のファイルをリストアップします。
`wallpaper_yyyymm_1.jpg`という名前のファイルを検索します。
今月の壁紙をダウンロードする前なので、対象のファイルを一度すべて消しちゃいます。
「先月の画像を削除する」という方法も考えましたが、1カ月以上パソコンをインターネット環境に接続しない場合に昔の壁紙が残ってしまうため、前の月以前の壁紙はすべて削除することにしました。

~~~python3
import glob
rmpic = glob.glob(r'C:\Users\ayk_f\wallpaper\wallpaper_*_1.jpg')
print(rmpic)
~~~
`glog.glog(<full_path>)`で正規表現を利用し対象ファイルを指定します。
`glog`とは python のモジュールの一つで、**特定のパターンにマッチするファイルを取得**することができます。
今回のように、`wallpaper_*_1.jpg`に当てはまるファイルを抽出する、といった場合に使えるみたいです。

~~~
$ ls
code/  wallpaper_202012_1.jpg  wallpaper_202108_1.jpg  wallpaper_202109_1.jpg
~~~

フォルダの中身はこんな感じです。
`wallpaper_202012_1.jpg`, `wallpaper_202108_1.jpg`, `wallpaper_202109_1.jpg` の3つが抽出できればOKです。

~~~
$ python wallpaper_v3.0.py
['C:\\Users\\ayk_f\\wallpaper\\wallpaper_202012_1.jpg', 'C:\\Users\\ayk_f\\wallpaper\\wallpaper_202108_1.jpg', 'C:\\Users\\ayk_f\\wallpaper\\wallpaper_202109_1.jpg']
~~~
対象の3つのファイルがフルパスで抽出できました。


# 抽出した画像の削除
対象ファイルの抽出ができたので、ファイルを削除します。
`for文`を用いて対象ファイル分だけ削除を実施する、という動きになります。

~~~python3
for t in rmpic:
    print("remove;{0}".format(t))
    os.remove(t)
~~~
おそらくですが、リストの0つ目、1つ目、2つ目・・・のように削除するみたいです。
ファイル名に整数が入っている必要はないみたいです。
※私はファイル名が `wallpaper_1.jpg`, `wallpaper_2.jpg`, `wallpaper_3.jpg` のようなファイルにしておかないといけないと勘違いしていたので、結構混乱しました・・・。

~~~
$ python wallpaper_v3.0.py
['C:\\Users\\ayk_f\\wallpaper\\wallpaper_202012_1.jpg', 'C:\\Users\\ayk_f\\wallpaper\\wallpaper_202108_1.jpg', 'C:\\Users\\ayk_f\\wallpaper\\wallpaper_202109_1.jpg']
remove;C:\Users\ayk_f\wallpaper\wallpaper_202012_1.jpg
remove;C:\Users\ayk_f\wallpaper\wallpaper_202108_1.jpg
remove;C:\Users\ayk_f\wallpaper\wallpaper_202109_1.jpg
~~~
`remove;<full_path>` で削除したファイルが出力されました。

~~~
$ ls
code/  
~~~
削除も無事にできています！
これで今回の任務は完了です。

# さいごに
今回もプログラムの改版でした。
日曜大工的な感覚でやってますが、思った通りに動き出すと楽しいですね。
いつかは他の人でも使えるように、画像の格納先を最初に登録するような挙動も入れたいな・・・・と思ったり。
人に「こんなの作ったよ！」って話すことで、思ってもなかった意見がもらえるのでそれも楽しかったです。

# 参考リンク
- [My Drive上にある画像（*.jpg)を一括削除したい。 - teratail](https://teratail.com/questions/298231)
- [Pythonでファイル・ディレクトリを削除するos.remove, shutil.rmtreeなど - note.nkmk.me](https://note.nkmk.me/python-os-remove-rmdir-removedirs-shutil-rmtree/)
- [【初心者向け】Pythonのglobを徹底解説！正規表現の書き方も説明 - Tech Teacher Blog](https://www.tech-teacher.jp/blog/python-glob/)
Rails * Vue の歴史を辿ってみる

# Rails * Vue の歴史を辿ってみる

---

# この話を読み終えてわかること

- Rails * Vueの歴史ってまだまだ浅いこと
- Rails * Vueの情報はググってみると、やり方が２つに別れていること
- 初学者でも、全然戦えるフィールドであること

---

# Railsの歴史

- 1995(26年前)
    - Ruby誕生、割と古くからある
        - 割と泣かず飛ばずの言語だった
- 2005(16年前)
    - RubyOnRailsが誕生
        - 有名企業が次々採用
            - Airbnb
            - twitter
            - GitHub
    - Rubyが注目され始めるタイミングが瞬間がここ

---

# Vueの歴史

- 2009年(12年前)
    - 土台であるnode.js誕生
        - WEB業界に衝撃を与えた
        - front, backの完全分業化の実現に大貢献
- 2014(7年前)
    - Vue.js誕生
        - 従来最強は
            - Facebook製のReact(2011〜)
            - Google製のAngular(2012〜)
        - そこに一石投じた1人の開発者[Evan You]によって誕生

---

# Railsさん、node.jsすげえに気づいて取り込み始める

- 2016年(5年前)
    - webpackの拡張GEM、webpackerを本気でサポート開始
        - node.jsのplugin管理をRails上でやりやすくしようと言う試み開始
        - ただ、node.jsをそもそも使ってた人たちから酷評される
            - webpackerは独自すぎて使いにくい

---

# その頃、Vueは

- 2016年(5年前)
    - Vue2.0が発足
    - これが強烈に評判がよく、一気に普及
        - github上でreactやangularのstar数を追い抜く
    - レスポンス早く、書きやすく、めちゃいいやんってなる

---

# RailsのWebpackerいらないトレンドが普及

- 2018年頃(3年前くらい)
    - 脱webpacker記事が増える
    - ならば、しっかりとfront, backを切り分けた方が良いでしょ。と言う流れに
    - node.jsをRailsの中で組み立てるのではなく
        - node.js環境とRails環境をそもそも分けてしっかり疎結合に

---

# そして最近のVueの動き

- 2020年(1年前）
    - Vue3.0がスタート
    - TypeScriptいいよね！の流れと仲良くするため？が強い印象
    - 一層、バグ少なく組みやすいcomposition APIをリリース

---

# ここまでの話からわかること

- 2009年(12年前)
    - WEBの世界は大きく変化があった。
- 2016年(5年前)
    - Vue.jsの躍進が始まった
- 2018年(3年前)
    - Rails * Vueのあるべき姿が見え始めた
    - なのでこの分野で見たら、3年プレイヤーくらいが最年長と言う感じ

---

# ここまでの状況を踏まえて

- Rails * Vueって、歴史そんなに深くない
    - この掛け算で戦ってる人達
        - まだ初学者の方でも、全然手の届く範囲で先駆者たちは走ってる
- さらにまだまだ進化は続くので、トレンドを追っていれば追い抜くのも難しくない
    - またみんな１年生に戻るかもしれないので

---

# というわけで

- 初学者の方も、焦ったり、すごい人見てげんなりしなくても大丈夫
- この分野に限ってはみんな若手
- 楽しんでたら、気がついたら追い越してるっていう可能性は全然あるので
    - 焦らず楽しんでいきましょうー！
【Rails】scopeではなぜfirstメソッドを定義しないのか


##きっかけ

下記のコードを見たときに少し違和感を覚えた。

```ruby
class Article < ApplicationRecord
  scope :published, -> { where(published: true) } 
end

```

```ruby
class ArticlesController < ApplicationController
  def index
    @article = Article.published.first
  end
end
```

firstメソッドをモデルのpublishedメソッドの中で書いてしまった方が
コントローラーが少しすっきりする気がするのになんでそうしてないんだろうと疑問に思ったので
scopeについて改めて調べてみた。


```ruby
class Article < ApplicationRecord
  scope :published, -> { where(published: true).first } 
end

```

```ruby
class ArticlesController < ApplicationController
  def index
    @article = Article.published
  end
end
```

##問題になりそうなケースと原因
例えば条件に合うArticleがない場合、nilが返るはずのところでなぜか全件取得されてしまうらしい。
これはscopeの中で行われている処理の結果がnilの場合、全件取得が行われる仕様になっているため。


##まとめ
scopeは「メソッドを定義するより１行ですっきり書けるもの」という認識しかなかったが
仕様をよく理解して適切に使っていきたい。



##参考

https://qiita.com/Ushinji/items/149eff5e3d45a6f0cd92

https://railsguides.jp/active_record_querying.html#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97
【PHP】配列ポインタ操作関数はIteratorを無視する

# 配列ポインタ操作関数にオブジェクトを突っ込む

やたらたくさんある[PHPの配列関数](https://www.php.net/manual/ja/book.array.php)ですが、大半は配列の全ての値に対して一律に処理を行う関数です。
キーと値を入れ替える[array_flip](https://www.php.net/manual/ja/function.array-flip.php)、特定のカラムを取り出す[array_column](https://www.php.net/manual/ja/function.array-column.php)、任意の関数を適用する[array_walk](https://www.php.net/manual/ja/function.array-walk.php)などですね。

ところでこの中に一部、配列のポインタを直接触る関数群があります。
キーを取得する[key](https://www.php.net/manual/ja/function.key.php)、値を取得する[current](https://www.php.net/manual/ja/function.current.php)、ポインタをひとつ進める[next](https://www.php.net/manual/ja/function.next.php)、ポインタを先頭に戻す[reset](https://www.php.net/manual/ja/function.reset.php)などです。

よく見るとこれらの関数、シグネチャが`array|object &$array`となっていて、実は配列以外にオブジェクトも反復動作させることができます。

となればIteratorを使って操作したくなるわけですが、ここには罠が存在します。


```php
class A implements IteratorAggregate{
	public $a = 1;
	public $b = 2;
	public function getIterator() {
		return new ArrayIterator([3, 4]);
	}
}

// foreach
$a = new A();
foreach ($a as $v) {
    var_dump($v); // 3, 4
}

// current
while ($v = current($a)) {
    var_dump($v); // 1, 2
    next($a);
}
```

なんかIterator無視するんですけど。

[Iterator](https://www.php.net/manual/ja/class.iterator.php)はPHPの機能のひとつで、オブジェクトの反復動作を任意に設定することができる機能です。
本来はオブジェクトを`foreach`すると[可視のプロパティが順に出てくる](https://www.php.net/manual/ja/language.oop5.iterations.php)のですが、それを異なる動作にすることができます。
のですが、配列ポインタ操作関数は反復動作とは関係ないので動作に影響しないというわけですね。
一見同じような機能なのに動作が違うということで、非常にわかりにくい挙動となっています。

しかも、このあたりの話はマニュアルにも全く書かれていません。
僅かに[foreach](https://www.php.net/manual/ja/control-structures.foreach.php)に書かれている『foreach は、 current() や key() のような関数で使われる、内部的な配列のポインタを変更しない点に注意して下さい。』がほぼ唯一の言及ですが、これの一文だけでIteratorが効かないとまで解釈しきれる人はそう多くないでしょう。


対策としては、そもそも今どき配列ポインタ操作関数を自力で使わないのが一番です。
ループ制御はオブジェクトだろうが配列だろうがforeach一択です。


ちなみに[ArrayObject](https://www.php.net/manual/ja/class.arrayobject.php)を継承すると、`getIterator`が存在するかどうかでforeachとnextの出力がかわります。
益々わけがわからない。

```php
class A extends ArrayObject{}

// foreach
$a = new A([1, 2]);
foreach ($a as $v) {
    var_dump($v); // 1, 2
}

// current
while ($v = current($a)) {
    var_dump($v); // 何も出力されない
    next($a);
}


class B extends ArrayObject{
    public function getIterator() {
        return new ArrayIterator([3, 4]);
    }
}

// foreach
$b = new B([1, 2]);
foreach ($b as $v) {
    var_dump($v); // 何も出力されない
}

// current
while ($v = current($b)) {
    var_dump($v); // 3, 4
    next($b);
}
```

# PHP8.1

この動作は非常にわかりにくいということで、PHP8.1以降は[配列ポインタ操作関数にオブジェクトを突っ込めない](https://qiita.com/rana_kualu/items/c894b2160d1f8799eed2#key-current-next-prev-and-reset-on-objects)ようになります。
PHP8.1でE_DEPRECATED、PHP9でエラーになる予定です。

```php
$a = new A([1, 2]);
while ($v = current($a)) {
    var_dump($v);
    next($a);
}
// PHP8.0まで エラー無し
// PHP8.1以降 E_DEPRECATED
// PHP9移行 エラー
```
【Vue.js】条件分岐 v-if について

#はじめに
こんにちは！　松本　佑大（まつもと　ゆうだい）と申します！
今回は条件分岐 v-if についてアウトプットしていきます！

#V-ifとは
条件分岐v-ifを利用することによって**要素に表示/非表示を切り替える**ことができます。

#書き方

基本的な書き方は以下のようになります。

```HTML:HTML
    <div id ="app">
       <p v-if="toggle">
          Good morning!
       </p>
    </div>
```

```Vue.js
var app = new Vue({
    el:'#app',
    data:{
      toggle: true,
    }
```

![スクリーンショット 2021-10-10 17.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2114750/abd8af73-1cd6-3c8f-9065-1b4b01a283d6.png)


プロパティ`toggle`（任意）を定義し、真偽値`true`or`false`を書きます。
（trueなら表示、falseなら非表示になります。）
次に`p要素`に`vーif`ディレクティブを設定し、値にはプロパティ`toggle`を指定します。
上記には`toggle:true`に指定してありますので、`Good morning!`が表示されています。

※v-ifでは表示/非表示が`display:none`ではなく、p要素そのものが削除される仕組みになっており、描画コストが高くなる恐れがあります。頻繁に表示/非表示を繰り返すのならば`v-show`ディレクティブを使用することを推奨します。（別記事で解説します）

#まとめ
・要素にv-if="プロパティ"を指定。
・data:{プロパティ:真偽値}を設置。

プロパティは任意になります！

#最後に

今回はv-ifについてアウトプットしました。
もし認識の仕方が間違っていましたら、コメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！
【Git＋GitHub】擬似チーム開発の手順・Issue管理

#はじめに
こんにちは。
こちらの記事では、現場に入ってからのチーム開発を想定し、１人で擬似チーム開発を行う方法を記しています。

##開発手順

* リモートリポジトリからローカルリポジトリへクローンする
* Issueの作成
* 開発用ブランチの作成
* 開発
* 差分の確認、ステージング、コミット、プッシュ
* GitHubでプルリクエスト作成、マージ
* ローカルリポジトリからリモートリポジトリへプルする
* 開発用ブランチの削除


###リモートリポジトリからローカルリポジトリへクローンする
GitHubを開いて、使用するリポジトリのURLをコピーして

```
git clone [URL]
```

をローカルのターミナルで実行します。

###Issueの作成
再びGitHub上で、上部のバーのIssuesに移動。
`New issue`を選択したら、タイトルとコメントを入力してIssueを作成。

###開発用ブランチの作成
開発用ブランチをローカルのターミナルで以下のコマンドを実行。

```
git checkout -b [開発用ブランチ名 #Issue番号]
```

上記のコマンドだと、

```
git branch [開発用ブランチ名]
git checkout [開発用ブランチ名]
```

ブランチの新規作成とブランチへの移動を合わせて行ってくれる。
コミットメッセージに` #Issue番号`を追加することで、コミットとIssueが連携されて、後から変更箇所が探しやすくなります。

###差分の確認、ステージング、コミット、プッシュ
開発した記述をリモートリポジトリへプッシュします。

```
git status     // ローカルリポジトリのファイルの変更や追加を確認
git diff       // ステージ - ワークツリー間（git addする前）の変更差分の確認

git add .
git commit -m "[コミットメッセージ  #Issue番号]"
git push origin [開発用ブランチ名 #Issue番号]
```

###GitHubでプルリクエスト作成、マージ
プッシュまで行うと、GitHubで`compare & pull request`を選択して変更内容を記述し、`create pull request`でプルリクエストを作成する。その際、開発用ブランチからメインブランチへのプルリクエストなのかも確認しておくと良い。
さらに`merge pull request`を選択してマージまで完了させる。

###ローカルリポジトリからリモートリポジトリへプルする
ローカルリポジトリとリモートリポジトリの状態を一致させるため、メインブランチでリモートの内容をプルする。

```
git checkout [メインブランチ名]
git pull origin [リモートリポジトリのブランチ名]
```

###開発用ブランチの削除
最後に不要になったブランチの削除を行う。

```
git branch -d [開発用ブランチ名 #Issue番号]
```

###Issueを閉じる
GitHub上で、今回使用したIssueをクローズする。

<br>

#おわりに
ここまで、擬似チーム開発の手順についてまとめました。
ネット上での情報を参考に作成しましたが、実際の現場によって流れや懸念点等あると思うので、ぜひコメントいただけると助かります！

参考にさせていただいた[こちらの記事](https://qiita.com/gold-kou/items/7f6a3b46e2781b0dd4a0)には、より詳しい説明がありますのでぜひ参照していただければと思います。

以上、最後まで読んでいただきありがとうございました！
よければLGTMを押してくれると嬉しいです！^^
RAIDのパリティデータとは？

## 勉強前イメージ

誤り訂正とかよく言うけどよくわからん

## 調査

### RAIDのパリティデータとは？

RAID5とRAID6でデータを複数のドライブに分散させる際に同時にパリティという冗長コードが生成されて書き込まれます。
誤り訂正補正とも言います。
パリティはデータ同様全てのディスク上に分散して書き込まれます。

これによってRAID5ではHDDのうち1台、RAID6では2台に障害が発生しても、残りのデータとパリティを元に欠損したデータを算出し、
完全な状態のデータを作ることができます。

HDDの台数が増えてもパリティ用のデータはRAID5であればディスク1本分の容量なので効率が高いです。

## 勉強後イメージ

パリティって生成されるのね！
知らなかった・・・
なんとなくイメージはついてたけど、
パリティ+残りのデータ→欠損データなのね
すごい。。。

## 参考

- [データ復旧業者が語るRAID5](https://www.ino-inc.com/raid/raid5.php)
Java Silver3

前回の続きです

https://qiita.com/0W5E8fPq1EOm4yE/items/7d548c1ef77523ccb8c2

今回はchapter3の演算子と分岐文です。

・値を代入する場合型変換は適用される(int型にcharを代入)

・キャストがないと代入できずコンパイルエラーになる

・「||」は1番目の式がtrueなら2番目の式は評価しない

・「&&」は1番目の式がtrueでも2番目の式を評価する

・「a++」はaに1を先に加算して代入する、「++a」はa先に代入して加算する

・switch文の式の結果はbyte,char,short,intおよびラッパークラス,enum,Stringの型(double、float、longは含まない)

・defaultがないとその後の処理も実行される

・1|2はビット演算子(二進数の合計3が返ってくる)

・equals()メソッドは同じ文字列かどうか比較する

・Stringクラスは読み取り専用クラスなのでオブジェクトが保持する文字列を書き換えることはない

・痴漢後の文字列を変数に再代入しているか確認する

・+演算子で文字列の連結は可能だが、-は不可能

・Stringクラスで生成した文字列は変わらないがStringBuilderクラスで生成した文字列は変更可能
【Ruby】injectについて

##inject
eachなどのようにブロック内の処理を繰り返し行うメソッド

1~5までの合計を計算する

```ruby
[1, 2, 3, 4, 5].inject {|sum, num| sum + num } 
#=> 15
```

↓上のコードと同じことをしている

```ruby
sum = 0
[1, 2, 3, 4, 5].each {|v| sum += v }
p sum   # => 15
```



初期値を指定して毎回のループでリセットすることもできる(デフォルトは初期値0なので省略可)

```ruby
[1, 2, 3, 4, 5].inject(1) {|sum, num| sum + num**2 }
#=> 56
```


##参考

https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/inject.html
【Android】「java.lang.AssertionError java.lang.NoSuchFieldException」が出たときの対処法

Androidで「java.lang.AssertionError java.lang.NoSuchFieldException」が出たときの対処法をご紹介します。

## 環境
Android Studio 4.1.3
kotlin 1.4.32
java 1.8.0_241

## 現象
Androidアプリの評価のため社内リリース版を公開して使用していると、ある箇所でアプリが強制終了しました。
そこでデバッグを有効にしてログを確認してみると以下のエラーが出力されていました。

```
java.lang.AssertionError java.lang.NoSuchFieldException: Open
```
「Open」は自分で定義したenumクラスの定数の一つです。
デバッグ版ではこのようなエラーが出ていなかっため、気づかずに社内リリースしていたようです。

## 解決法
[こちらの質問](https://stackoverflow.com/questions/57790047/getting-java-lang-assertionerror-java-lang-nosuchfieldexception-http-1-0)の回答通りにproguard-rules.proに以下のコードを追加すると問題なく動作するようになりました。

```
-keepclassmembers enum * { *; }
```

## 参考
・https://developer.android.com/studio/build/shrink-code?hl=ja
・https://qiita.com/boohbah/items/7372b29637d28e6d671c
・https://stackoverflow.com/questions/57790047/getting-java-lang-assertionerror-java-lang-nosuchfieldexception-http-1-0
Vim 内から実行環境を判定する(主に Windows)

```vim
if has('win32')
  " Windows ローカル (64bit版でも has('win32') は 1 を返す)
elseif has('win32unix')
  " msys2, Cygwin など Unix環境を再現したもの (ただし WSL は除く)
else
  " その他のパターン(WSL も含む)
endif
```

WSL なのかそうでないかの判定ができない。
現状、`isdirectory('/mnt/c)` が 1 であるかどうかで判定するしかないだろうか？
【備忘録】Rの古いパージョンのパッケージをインストールしたい

# Rで古いパッケージのインストールを行いたい

Rのバージョンが3の開発環境で、Rのバージョンが4以上の環境じゃないと必要なパッケージがインストールできなかった時の対処法に関する備忘録です。

## Rの古いバージョンのパッケージのインストール方法例
今回は、Rのバージョンが3.6の環境下で、最新のパッケージがRのバージョン4.0.0以上じゃないとパッケージがインストール出来なかった事象例と解決策を記載する。

2021/10月時点でパッケージfastICAをインストールしようとすると以下のようにRのバージョンが3.6.3ではインストール出来ないっていうエラーが発生する。

```
> install.packages('fastICA')

 パッケージを ‘/usr/local/lib/R/site-library’ 中にインストールします 
 (‘lib’ が指定されていないため) 
 警告:   リポジトリー https://cran.r-project.org/src/contrib/Archive/fastICA/fastICA_1.2-2.tar.gz/src/contrib に対する索引にアクセスできません :
   URL 'https://cran.r-project.org/src/contrib/Archive/fastICA/fastICA_1.2-2.tar.gz/src/contrib/PACKAGES' を開けません 
 警告メッセージ: 
 パッケージ ‘fastICA’ が利用できません (for R version 3.6.3) 
```

[fastICAのパッケージに関するドキュメント](https://cran.rproject.org/web/packages/fastICA/index.html)を確認すると、fastICAはRのバージョンが4.0.0以上のR実行環境で動作すると記載されている(つまり、Rのバージョンが4.0.0未満の場合は正しくインストールされないみたい)。

```
Version:	1.2-3
Depends:	R (≥ 4.0.0)
Suggests:	MASS
Published:	2021-09-25
Author:	J L Marchini, C Heaton and B D Ripley
Maintainer:	Brian Ripley <ripley at stats.ox.ac.uk>
License:	GPL-2 | GPL-3
NeedsCompilation:	yes
In views:	ChemPhys, Multivariate, Psychometrics
CRAN checks:	fastICA results
```
そこで、[fastICAのアーカイブ](https://cran.r-project.org/src/contrib/Archive/fastICA/)から旧fastICAのバージョン1.2.2のtar.gzのurlリンクをコピーし、インストールしたいRの環境上にてコピーしたurlリンクを使って以下コマンドを実行する。

```
install.packages('https://cran.r-project.org/src/contrib/Archive/fastICA/fastICA_1.2-2.tar.gz', repos=NULL, type='source')
```

すると、Rが3.6.3のインストール環境下でパッケージfastICAのバージョンが1.2.2として正しくインストールされることが出来る。
G検定取得に向けた学習

## はじめに
まだエンジニアでなかった昨年、G検定2020#2の資格を取得した。
思い立ってから半年ほど、独学で資格を取得している。
学習時間は100時間ほど。のんびりと学習し、ラスト一週間でスパートをかけた。
自身がどのような勉強を行なったか、記録しておく。

## 事前準備がモノを言う

* **基本的な知識は瞬時に解答できるようにする**
* **すぐに参照できる要点シートを作成する**

学習自体もそうだが、**学習内容をまとめた索引を作っておく**といい。
ドキュメントやスプレットシートで検索しやすいように作成するのがポイントだ。
わからないこと、忘れたことがあれば試験中にすぐ参照できる。
しかし、設問200〜220問に対し、試験時間は120分という時間制限があり
**一問あたり30秒〜40秒ほどで回答せねばならない。**
基礎内容はすぐ解答し、検索しやすいシートで参照時間を短縮する。
そうすれば、全問回答も十分に可能だ。

##使用した学習教材

* [白本](https://www.amazon.co.jp/gp/product/4798157554/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=1) …公式テキスト
* [黒本](https://www.amazon.co.jp/gp/product/4295005665/ref=ppx_yo_dt_b_asin_title_o08_s00?ie=UTF8&psc=1) …問題集
* [Study-AI](https://study-ai.com/)の模擬テスト
* AI関連のニュースサイト

テキストなくてもネット情報で十分な気はしたが、安心を買った。

##学習の流れ
まずは**白本を何度か読む。**
最初に押さえておくべきベーシックな情報が全て詰まっているので、ここで大枠を抑える。
この時点で**テキストを読みながら索引を作っておく**のが正解だ。
また、白本の章末問題は完璧に答えられるようにしておこう。
基本的な問題しかないが、何某かは間違いなく出題される。

次に、**黒本の問題をひたすら解いていく。**
白本よりも詳しく解説されていたり、補足的な問題、解説がある。
一通り正解できるようにしつつ、**索引を補足**していくといいだろう。

そして、**Study-AIの模擬問題をひたすら解いていく。**
問題内容も然ることながら、当日の出題形式に慣れることが目的だ。
**適切であるもの**または**適切でないもの**を、**単数**または**複数**選択していく。
このパターンが入り混じって出題されるので、意外に厄介だった。
時間がないと焦ってさらりと読み飛ばしてしまうが、危険なので**問題文はちゃんと読もう。**

ここまでで8割は問題なく取れると思う。
最後に、**AIの時事問題**。
これは過去問で傾向を見つつ、**最新情報を押さえておく**必要がある。
テキストも出ているが、テキストになっている時点で情報が古い。
ここに関しては、**ニュースサイトを見る方が良い。**

##最後に
G検定は有名で、**様々な方がサイトやQiitaにまとめ記事を書かれている。**
試験当日の索引にそのまま使えそうな記事も多くある。
そういったページを参考にすれば、学習はぐんと楽になるだろう。
ただ、そういった記事を参照するだけでは付け焼き刃になる。
**自身での学習も手を抜かないよう、頑張っていただきたい。**

**G検定は何度でも取得できる資格**だ。
繰り返し取得することで知識の定着、アップデートが行える。
私もまた改めてG検定に挑戦しようと思う。
選択中のメールからConversationツリーの最初のメールを表示

これを作りたい

https://twitter.com/MasazaneKunohe/status/1446610651267305472?t=Kx-w9qlv5oaLaud9madUKw&s=19



第一歩として、メール一覧から、現在選択中のメールかの返信元をさかのぼり、親がなくなる最初のメールを開くものを作りました。

道中で見つかった各メールは`myParents`に格納していきます。




子メールさがし方向は分岐があるだけでなく、`.GetConversation.GetChildren(CurItme).Item(1)`と最初の要素だけを切り抜こうと思ってもうまく行かないので少し難易度が上がりそうです。。。

``` vb
Sub Conversationツリーの最初のメールを表示()
  Dim CurItme As Outlook.MailItem
  Dim myParents() As Outlook.MailItem
  
  Set CurItme = ActiveExplorer.Selection.Item(1)
  With CurItme
    Dim k: k = 0
    ReDim myParents(k)
    Set myParents(k) = .GetConversation.GetParent(CurItme)
    
    Do Until myParents(k) Is Nothing
    
      Debug.Print k
      Debug.Print myParents(k).SentOn
      Debug.Print myParents(k).SenderName
      
      k = k + 1
      ReDim Preserve myParents(k)
      Set myParents(k) = .GetConversation.GetParent(myParents(k - 1))
    Loop
  End With
  
  myParents(k - 1).Display
  
End Sub
```
VB 6.0から2008（.Net）へアップグレード


Visual Basic 6.0 からVisual Studio 2019へアップグレードできないため、2段階アップグレードする必要があります。

今回はVisual Basic 6.0 からVisual Studio 2008へへアップグレードを紹介したいと思います。

## 作業順番
①Microsoft Visual Studio 2008をダウンロードする
➁Visual Studio 2008でVB6.0のソースをアップグレードする


## ①Microsoft Visual Studio 2008をダウンロードする

Microsoftサイトから下記のリンクでVisual Studio 2008をダウンロードしてインストールを実施する
　https://www.microsoft.com/en-us/download/details.aspx?id=13276

該当言語、システム要件を確認の上、ダウンロードを実施する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/eb6e7c55-11ea-4dd1-2e64-ec0f73912fb1.png)

## ➁Visual Studio 2008でVB6.0のソースをアップグレード
Visual Studio 2008でVB6.0のソースを開く時にアップグレード画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/c8b76052-7780-30d6-4086-b01c3d2797bb.png)

【次】ボタンを押下すると、プロジェクトタイプを選択する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/e41187cf-ecc5-631e-5a62-2e3b587e0e7d.png)

VB6.0のソースからアップグレードする際に新規プロジェクトを作成する必要があり、新規プロジェクトのパスを指定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/dd8564a9-76a3-081f-57ea-cba4ac4cf888.png)

【次】ボタンを押下すると新規プロジェクトを作成して、ソースのアップグレードを準備する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/b1ba9239-755b-6fa6-6ec8-813b728296a0.png)

【次】ボタンを押下すると、アップグレードを開始する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387054/72d46e25-dd52-c104-5953-b93b8272dc8c.png)

アップグレードが完了したら、Visual Studio 2008で新規プロジェクトにて.Netへアップグレードしたソースが表示されます。

VisualStudioへマイグレーションに関して詳細サービスは記載がありますので、ご参照ください。
https://onetech.jp/service/migration-service
AWS ACM DNS検証　CNAMEレコードを登録する際に気になったこと

# AWS　ACMのDNS検証について
AWS ACMにはパブリックドメインの証明書を発行する際、DNS検証という仕組みがある。
DNS検証の仕組みを用いると証明書の更新が自動的に行われるため運用が楽になる。
※証明書の有効期限はどんどん短くなって現状は397日＝約13ヶ月。

CNAMEレコードを登録する場合は以下の２パターン。
①Route53にてドメイン管理を使用している場合→Route53のホストゾーンに登録。
②外部のレジストラでドメイン管理している場合→ドメインレジストラ（お名前.comとか）の管理のページでCNAMEレコードを登録。


# CNAMEレコードを登録するときに気になったこと
例えば*.hogehoge.comというパブリックドメインがあるとして、
上の名前ですでにDNS検証が行われていた場合、同じドメインで新たに発行したCNAMEレコードを追加しても
問題ないのか気になったのでサポートに問い合わせてみた。

Aアカウント　*.hogehoge.com DNS検証済み。
Bアカウント　*.hogehoge.com DNS検証（新規）。

サポートの回答によると**「アカウント毎に新しいレコードが発行されるため問題ない」**とのこと。
**CNAMEは新規追加になるので既存のレコードが変わるわけではない**ので大丈夫！

よくよく調べてみると以下のページに記載があった。
そもそも**アカウントやリージョンをまたいで同じ証明書は使えない。**
なのでアカウントやリージョンをまたいで同じドメインで証明書を発行したい場合は都度、
以下の①～③を実施する必要がある。
**①発行したいアカウント+リージョンを選択。
②ACM上で対象ドメインの証明書をリクエスト。
③DNS検証のCNAMEレコードをRoute53のホストゾーンまたはレジストラに登録。**
https://aws.amazon.com/jp/premiumsupport/knowledge-center/acm-export-certificate/
JavaScriptのスコープをマスターしよう!!

# はじめに
初学者です。
スコープについて学習したので備忘録。
間違っていたら教えていただけると幸いです。

# スコープとは
スコープとは「実行中のコードから値と式が参照できる範囲」です
スコープによって呼び出せる関数や変数に違いがでます。

# スコープの種類
スコープにはいくつかの種類があります
1. グローバルスコープ
1. スクリプトスコープ
1. 関数スコープ
1. ブロックスコープ

# 各種スコープの説明

## グローバルスコープ
グローバルスコープはグローバルコンテキスト内でvarやfuntionで定義した定義物です。
グローバルスコープに分類されるものはグローバルオブジェクト(windowオブジェクト)のプロパティとして値が保持されているものです。

## スクリプトスコープ
スクリプトスコープはグローバルコンテキスト内でletやconstで宣言された宣言物です。関数宣言を使わずに関数式で作成た関数も
スクリプトスコープに分類されます。
グローバルスコープとスクリプトスコープは厳密には違うスコープですが、どこからでも呼び出すことができるという点で
どちらも**グローバルスコープとして扱われることが多いです**

```javascript
window.a = 0
console.log(window.b)//省略しない呼び出し方
console.log(b)//省略した呼び出し方
```
*グローバルオブジェクト(windowオブジェクト)に保存されている値でもwindow.を省略して呼び出すことができるため、参照の仕方＋どこからでも呼び出し可能な点はスクリプトスコープと違いがありません。*
*厳密にスコープを分けると下記のようになりますが、どちらもグローバルオブジェクトと呼ばれることが多いです*

```javascript
let a = 0; //Script scope
var b = 0; //global scope
function c() {} // grobal scope
```

## 関数スコープ
```javascript
function a (){
let b = 0;
console.log(b)//○
}
a();
console.log(b)//x
//関数の中と外ではスコープが違う
```

## ブロックスコープ
```javascript
{
  let c = 1;
  console.log(c)//○
}
console.log(c)//x
//関数式以外の波括弧で囲まれた範囲をブロックスコープという
//使用するための条件 let or constを使う  varはx
//関数式は無視されるため変数宣言で関数を作る
//基本はforやif文で生成される
```

## レキシカルスコープ
スコープの種類では出しませんでしたが、番外編と思ってください。
**実行中のスコープからみた外部スコープがレキシカルスコープです**

```javascript
let a = 2
function fn1() {
  let b = 1
  function fn2() {
    let c = 3;
    console.log(b)//○
  }
  fn2()

}
fn1();

//fn1はfn2のレキシカルスコープ(外部スコープなので)bを参照することができる
```
```javascript
let a = 2
function fn1() {
  let b = 1
  
}
fn1();

function fn2() {
  let c = 3;
  console.log(b)//x
}
fn2()
//こちらのコードではfn2のレキシカルスコープにある変数や関数はaと関数fnの2つ
//fn2の中にあるbは参照できない
```

# まとめ
グローバルスコープはグローバルオブジェクト(windowオブジェクト)に保存される変数や関数
スクリプトスコープはグローバルコンテキスト内でletやconstで宣言されたもの
関数スコープは関数の{}の中の記述(関数宣言に限る)
ブロックスコープは関数宣言された{}以外の{}の中（forとかifとかの{}）
レキシカルスコープは実行中のスコープからみた外側のスコープ
[C#] ブール値を反転させて再代入するときの超短い書き方

`true`と`false`を反転させて再代入するとき、`!`演算子を使ってやればいいんですが、長ったらしい変数だとちょっとヤです。

```c#
var longNameBecauseGoodNameOmoitsukankatta = true;
longNameBecauseGoodNameOmoitsukankatta = !longNameBecauseGoodNameOmoitsukankatta;
Console.WriteLine(longNameBecauseGoodNameOmoitsukankatta); // false
longNameBecauseGoodNameOmoitsukankatta = !longNameBecauseGoodNameOmoitsukankatta;
Console.WriteLine(longNameBecauseGoodNameOmoitsukankatta); // true
```

そんなときは`xor`演算子の`^`を使いましょう。`A XOR true`は`NOT A`と等価のため、代入演算子`^=`を使うとこんなふうに書けます。

```c#
var longNameBecauseGoodNameOmoitsukankatta = true;
longNameBecauseGoodNameOmoitsukankatta ^= true;
Console.WriteLine(longNameBecauseGoodNameOmoitsukankatta); // false
longNameBecauseGoodNameOmoitsukankatta ^= true;
Console.WriteLine(longNameBecauseGoodNameOmoitsukankatta); // true
```

C# 7.2 から拡張メソッドの第一引数に`ref`をつけられるようになったので、以下の拡張メソッド定義をすると反転値の代入ということがわかりやくなるかもしれません。`.Reverse()`は10文字、` ^= true`は8文字なのでちょっと不利ですが・・・。

```c#
public static class Ext
{
    /// <summary>ブール値を反転して自分自身に設定し、その結果を返します。</summary>
    /// <return>反転後のブール値</return>
    public static bool Reverse(ref this bool b) => b ^= true;
}

bool a = true;
System.Diagnostics.Debug.WriteLine(a);
System.Diagnostics.Debug.WriteLine(a.Reverse());
System.Diagnostics.Debug.WriteLine(a);
System.Diagnostics.Debug.WriteLine(a.Reverse());
System.Diagnostics.Debug.WriteLine(a);
/* 実行結果
True
False
False
True
True
*/
```
スクロールしたら画像が拡大するやつ〜

(※この記事は、storyboardにスクロールビューを貼る基礎知識がある人を前提にしています。)

今回は、スクロールビューを上にスクロールしたら(下に引っ張ったら)、画像(ヘッダー画像)が拡大するやつを実装していきたいと思います。

こんな感じのやつです↓

![qiita用動画.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106647/e148b7db-11b1-388b-dc4e-bcfd0d9b2dea.gif)

(少しカクついてますが、実際ビルドするとちゃんとなめらかに動きます)

ちなみに今回の方法は、結構いろんな方々が記事として既に投稿してますが、僕のはその中でも一番シンプルな方法だと思います。

なので、「もっと詳しく理解したい！」という方は、他の記事を参考にしていただければと思います。

ではいきましょう！

<h1>はじめに</h1>

①ではまず、スクロールビューを用意しましょう

②そしてその上に、拡大させたいビューを置いてください

そうすると、こんな感じになります。

![スクリーンショット 2021-10-09 22.13.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1106647/42174c05-3016-da69-18c0-e4286de2f95f.png)

scrollViewと拡大させるImageViewの間にviewを入れるのも忘れずに〜

<h1>コード</h1>

ではコードに移ります。

まずは、完成型から

```php

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var scrollView : UIScrollView!
    
    @IBOutlet weak var expansionImageView : UIImageView!
    
    private var frameHeight : CGFloat!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        scrollView.delegate = self
        
        frameHeight = self.expansionImageView.frame.size.height
    }


}

extension ViewController : UIScrollViewDelegate{
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
    
        let offsetY = scrollView.contentOffset.y
        
        if offsetY < 0{
            
            let ToPlusOffsetY = offsetY * -1
            
            let newY = ToPlusOffsetY * -1
            
            let newHeight = ToPlusOffsetY + frameHeight
            
            expansionImageView.frame = CGRect(x: 0, y: newY, width: view.frame.size.width, height: newHeight)
        }
    }
}


```

では解説していきます。

当たり前ですが、まずはさきほどstoryboardで設定したオブジェクト達をこのコントローラーに繋げてください。

そして、そのスクロールビューが持つメソッドである「ScrollViewDidScroll」を呼び出してください。これは、スクロールビューがスクロールしたときに呼ばれるメソッドです。

※あ、デリゲートを自分に委任することも忘れずに。順番的には、委任先を指定⇨メソッドを呼ぶがベターだと思います。

ちなみに、「スクロールビュー」というのは、TableViewやCollectionViewも自動的に保持しているものですので、明示的にScrollViewそれ自体に拘らなくても大丈夫です。

そして、scrollViewDidScrollの中に、スクロールビューが移動する量を「offsetY」という変数として持たせます。

この「scrollView.contentOffset.y」というのは、「縦方向にどれだけ移動したか」という意味です。
逆に「scrollView.contentOffset.x」であれば、「横方向にどれだけ移動したか」になります。

そして、その変数が0以下になれば、つまり「縦方向にどれだけ移動したか(縦方向に移動した移動量)が、0以下になれば(上に行けば)」、という構文をif分で作ります。
※「y」は、上に行けば行くほどマイナスの値になります。

そしてその中で、まずは取得した移動量をプラスに変換する変数(ToPlusOffsetY)を準備します。

さらに、それをもう一度マイナスの値に変換して変数として持たせます。(Yをさらに上に動かすため)

次に、さきほど定義したToPlusOffsetYと、グローバルにすでに持たせているframeHeight(画像の現在の縦サイズ)を足して、変数化します。

そして最後に、拡大させたい画像のサイズに、newYやnewHieghtを含めた新しいサイズを代入します。

こうすることで、思うように動くようになると思います。

<h1>最後に</h1>

シンプル過ぎてすみませんでした！
まずはココから！Azure IoT を効率良くかつ段階的に学ぶ「コツ」 

#Azure IoT は難しい？どうやって学べば良いの？
Azure IoT の勉強を始めてみたけど、難しくて断念しました… なんて話を良く聞きます。
何故、「難しい」のか？

一番多く聞く理由は**「ドキュメントを読んでみたけれど、途中で良く分からない用語が沢山でてきて断念しました。」**という話。
Azure IoT に限らず、何か新しい事を習得する時には起こり得る問題ですね。

この記事では、そのようなお悩みをお持ちの方に、**Azure IoT を学ぶ「コツ」**をご紹介します。

##「難しさ」はどこから来るのか？
例えば、「IoT Edge」について調べ始めた時。
デバイスをIoT Hubに繋ぐ部分の説明で、「接続文字列 (Connection string)」とか、「Device Provisioning Service (DPS) 」なんて用語が普通に出てきます。

前提知識として「IoT Hub」の仕組みを知っていないと、いきなり理解するのは難しいかもしれません。逆に、先に「IoT Hub」を知っていれば、その知識がベースとして役に立つはずです。
もう少し高度な話になると、例えば **Azure Video Analyzer** や **Azure Percept** などの応用的な(高度な)サービス。こちらでも、IoT Hub や IoT Edge などがベースの技術として採用されています。

- [Azure Video Analyzer のドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-video-analyzer/video-analyzer-docs//?WT.mc_id=AZ-MVP-4040034)
- [Azure Percept のドキュメント](https://docs.microsoft.com/ja-jp/azure/azure-percept/?WT.mc_id=AZ-MVP-4040034)

つまり、「IoT Hub」や「IoT Edge」などは、前提知識として知っておくべき。もしくは、知っておく事で、後々役に立つんです。(トラブルシューティングの時とか)

##「難しさ」は「段階的に学ぶ」事で攻略しよう
という訳で、IoTを学ぶコツとして、Microsoft Docs&Learn のコレクションで「[効率良くかつ段階的に学ぶ Azure IoT の基礎](https://docs.microsoft.com/ja-jp/users/mode8086/collections/d44jfed20n23gd)」を作ってみました。
![DandL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493219/cf9a6954-92b8-45b7-4573-e070255c900b.png)

中身は無償で学べる[Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/?WT.mc_id=AZ-MVP-4040034) のコンテンツですが、Azure IoTをどのような順番で学んで行けば良いかを考えてモジュールを構成しました。
全て、初級・中級レベルのモジュールで構成していますので、これからIoTを学び始める方にも安心です。
是非ご活用ください！
laravel facebookログインをローカル環境でテストしてみる。

## 初めに
Facebook,Twitterログインをlaravelに実装したいけど、
それぞれの管理画面で見ると、localhostでは実装できないようになっている。
過去の記事では、できてたようですけど、厳しくなったらしい。
https必須とも記載ありました。

ngrokを使えば、HTTPSでも提供してくれるしできるんじゃね？と思い、試してみました。
SNSログイン完了後に情報を取得するまでが目的です。

## 結論
ngorkで発行されたURLをそれぞれのSNSの設定画面 コールバックURLを登録し、
.envに記載することでローカル環境でテストできました。

## 注意点
ngrok の無料プランは接続する度、払い出されるアドレスは変更されるので、
SNSの管理画面のリダイレクトuriと .envの APP_URLは都度変更が必要です。
めんどうであれば、有料プランに変更しましょう。

サーバーに公開する以外で他に簡単な方法あれば教えてください。
[Flutter Package] just_audio で (-11849) Operation Stopped が起きる

# エラー
https://github.com/ryanheise/just_audio/issues/520

iOSで起きますね。これとおんなじだと思います

# 解決策
キャッシュの不整合だと思われるので`main()`とかで毎回キャッシュをクリアすれば治ると思います。
ただキャッシュをクリアするメソッドが厄介でキャッシュがなかった場合

```dart
import 'package:just_audio/just_audio.dart';

void main() async {
  await AudioPlayer.clearAssetCache();
  runApp(MyApp());
}
```

初回起動時などキャッシュが作成されていないときは容赦なくクラッシュするので、音声がエラーでロードされないなっていうときに適宜実行すればいいと思います

https://github.com/ryanheise/just_audio/issues/428

ここでも言われてますね。アディオス
[GitHub] ブランチ（branch）

# ブランチ（branch)とは
作業を分岐させて履歴の流れを記録していくもの。
分岐したブランチは他のブランチの影響を受けないため、同じリポジトリ内で複数の変更を同時に進めることができる。


# ブランチのメリット
ブランチのメリットは以下が挙げられる。
■　プロジェクト本体に影響を与えずに作業ができる。
■　ブランチを切ることで目的別に同時並行で作業ができる。
■　不具合が発生した場合の対応が容易にできる。

# ブランチの操作
ブランチを操作するためのコマンドを紹介する。
####■ ブランチを作成
ブランチは**branch**コマンドで作成する。

```
git branch <ブランチ名>
```
また、ブランチの一覧を確認する場合は引数を指定せず実行する。

####■ ブランチの切り替え
作成したブランチ間を移動する場合、**checkout**コマンドを使用する。

```
git checkout <ブランチ名>
```

**checkout**コマンドに「**-b**」のオプションを指定すると、ブランチの作成と切り替えがまとめて行える。

####■ ブランチのマージ
**マージ**とは、現在のブランチに他のブランチの変更を統合させることで、**merge**コマンドを使用する。

```
git merge <ブランチ名>
```

####■ ブランチの削除
不要になったブランチを削除する場合は、「**-d**」オプションを指定する。

```
git branch -d <ブランチ名>
```


#まとめ
ブランチについて、メリットやコマンドについてまとめた。
次は、Gitのブランチモデル「**git-flow**」について学んでいきたい。
JavaScriptのCall stack (コールスタック)

# はじめに
初学者です。
コールスタックについて学習したので備忘録

# コールスタックってなんぞや？
**実行中のコードがたどってきたコンテキストの積み重ね**
**JavaScriptエンジンがどのような経路を辿ってコードにたどり着いたのか記録している**

# 実際のコードで確認しよう

```JavaScript
function a() {
}
function b() {
  a();
}
function c() {
  b();
}
c();
```

**コールスタック**
aの関数コンテキスト
bの関数コンテキスト
cの関数コンテキスト
ブローバルコンテキスト

*常に最上部が実行中のコンテキストになる
処理が完了すると上から徐々に消えていく*

# LIFO
*コールスタックの仕組みは「後入れ先だし」LIFO*
**(Last In, First Out)という**

# まとめ
Call stack(コールスタック)とはコンテキストの積み重ね。
Last In, First Out(後入れ先だし)で住み重なる
処理が完了すると最上部から消えていく
LINE WORKS の外部連携ユーザーの UUID の移行方法 (PowerShell)

LINE WORKS の 2021 年 9 月 9 日のアップデートで、監査やアーカイブでの LINE ユーザーの表示形式が変更されました。

https://line.worksmobile.com/jp/update-info/20210909/

外部の顧客管理システムなどで LINE WORKS でやり取りしている LINE ユーザーの情報を管理するために、UUID を使っていた場合などに、resourceId へ変更が必要な場合があると思います。

こちらのページの API を使って、UUID を基に resourceId を確認することができます。
TITLE: (旧) 個人アドレス帳の外部ユーザー UUID (worksAtContactNo) の移行
URL: https://developers.worksmobile.com/jp/document/100600207?lang=ja

API の構文は以下のとおりです。

```
https://apis.worksmobile.com/r/{API_ID}/contact/v3/domains/{domainId}/migration/worksAt/{worksAtContactNo}
```

PowerShell で実行する例を以下に示します。

```
Invoke-RestMethod -Uri "https://apis.worksmobile.com/r/<API_ID>/contact/v3/domains/<domain_id>/migration/worksAt/<worksAtContactNo>" -Method Get -Headers @{Authorization = "Bearer <Server_Token>"; consumerKey = "<consumerKey>"} 
```
次のように、出力されます。

```
worksAtResourceId                    sharedContactResourceIds
-----------------                    ------------------------
7df82329-fc31-4feb-4392-04a2b7a55f2a {507b4042-6f1e-4855-507f-040a8e79ce55}
```
worksAtResourceId が外部ユーザーのリソース ID です。
QiitaでMarkdownのNoteのスタイルが適用されない場合があるため検証してみた

Update (2021/01/07): Qiita運営様の迅速なご対応により、こちらの不具合は既に修正されております
詳細については、下記のリリースノートをご覧頂ければと思います

https://qiita.com/release-notes#2021-11-10


Qiitaの記事を書いていたところ、Markdownの**Note**(補足説明を書く為の機能)で書いた際に
スタイルが適用されない場合があったため、検証してみました

Noteに関しては、下記の「Markdown記法 チートシート」の 「Note - 補足説明」のところで紹介されています

https://qiita.com/Qiita/items/c686397e4a0f4f11683d#note---%E8%A3%9C%E8%B6%B3%E8%AA%AC%E6%98%8E


とりあえず、表示検証用に下記の内容を記載してみました

Markdownでの表記内容↓

```
:::note info
インフォメーション
(note info)
:::

:::note warn
注意
(note warn)
:::

:::note alert
警告
(note alert)
:::
```

実際にスタイルが適用される内容↓ 

:::note info
インフォメーション
(note info)
:::

:::note warn
注意
(note warn)
:::

:::note alert
警告
(note alert)
:::

正常にスタイルが適用されていれば、緑、黄色、赤の背景色やそれぞれのアイコンなどが表示されているはずです

では、いくつかのパターンで記事の表示を確認してみたいと思います

## 記事編集中のプレビュー画面

こちらの記事を編集中のプレビュー画面で確認してみます

![2021-10-21_16h11_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1969354/c5de665e-c416-45fc-5032-71cc1fa5347c.png)



問題無くスタイルが適用されていることが確認出来ました

## 下書き一覧のプレビュー画面

先程の記事を下書きとして保存し、下書き一覧のプレビュー画面で確認してみます

![2021-10-21_16h13_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1969354/836bebaf-0377-c99e-88ad-16cc074b8aae.png)

編集中のプレビュー画面と同じ状態で表示されました
こちらも問題無さそうです

## 限定共有投稿した記事

では、下書きを「限定共有投稿」で投稿して確認してみます

![2021-10-21_16h15_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1969354/bb7cbcce-d574-70a2-928d-8f3e539f88f6.png)


noteで書いた箇所が文字列しか表示されていませんね。。
スタイルが何故か適用されていないようです。。

ちなみにここまで下記の環境で確認していました

* 検証環境
    * OS: Windows10
    * ブラウザ: Google Chrome

### Firefoxで確認

一応、Firefoxでも確認してみます

![2021-10-21_16h17_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1969354/34d28124-da34-13f4-2f4d-0c1c6df279be.png)

やはり、こちらでもスタイルが適用されていないようです。。

### MacのSafariで確認

Mac Book ProのSafariでも確認してみました

![スクリーンショット 2021-10-21 16.20.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1969354/0522873c-ed9d-3d47-359f-d363a3e3cf3c.png)

こちらも同様にスタイルが適用されませんね。。

## 「全体に公開する」で公開した記事

限定共有公開で投稿した記事を「全体に公開する」で公開して確認してみます
予想では、他の方が書かれている記事では、問題無くスタイルが適用されていたので、恐らく正常に表示されると思うのですがいかがでしょう

![2021-10-21_16h29_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1969354/65668589-8359-ab5c-edb2-d0d7146addeb.png)

やはり、全体に公開した場合は、問題ありませんでした

## まとめ

結果として、何故か限定共有投稿の場合だけnoteのスタイルが適用されないようです。。
別のブラウザでも試してみましたが、同じく適用されていないため、恐らく表示まわりにバグがあるのでは無いかと。。
Qiita運営様、確認と修正の方をお願い致します！

2021/10/26更新
Qiita運営様にご報告しまして、こちらの不具合の件をIssue化して頂けたようです！
ありがとうございます！引き続き、よろしくお願い致します！

2021/11/10更新
こちらの不具合は修正されたとのことです！ありがとうございました！
rails 管理者が全Userの投稿削除をする（備忘録）

# はじめに

備忘録的に書いておくので、少しちがっているところもあるかもしれません😭
説明も薄めです、ご了承ください。

Ruby on rails をつかって、Twitterアプリをつくっています。管理者が自分の投稿以外の、あらゆるユーザーの投稿を消せるようにしたいと思います。

ユーザー登録はGemのdeviseで実装しています。

# Userに管理者を追加する
```java:ターミナル
 rails g migration AddAdminToUsers
```

```java:xxxxxxxxx_add_admin_to_users
 class AddAdminToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :admin, :boolean, default: false　#ここを追加
  end
end
```
```java:ターミナル
 rails db:migrate
```
次にseedファイルに管理者権限を持つユーザーを追加します。

```java:db/seeds.rb
 User.create!(username:  "管理者",
             email: "admin@example.jp",
             password:  "11111111",
             password_confirmation: "11111111",
             admin: true)
```
```java:ターミナル
 rails db:seed
```
# 管理者用のコントローラーをつくる

```java:ターミナル
　rails g controller admin::tweets
```

```java:controller/admin/tweets_controller
　class Admin::TweetsController < ApplicationController
   #  before_action :authenticate_user!も必要なら書いてください！
　　before_action :if_not_admin
 　 before_action :set_tweet, only: [:index, :new, :create, :show, :edit, :destroy]　#onlyのアクションは必要なものだけ書いてください
 
 #中略 def indexとか必要なものを書いてください！

　　private
  　　def if_not_admin
    　　redirect_to root_path unless current_user.admin?
  　　end

  　　def set_tweet
    　　@tweet = Tweet.find(params[:id])
  　　end
  end
```

# Routing設定
以下のコードを追加してください

```java:config/routes
resources :tweets 
  namespace :admin do
    resources :tweets, only: [:index, :new, :create, :show,  :edit, :destroy]
  end
```

# viewの設定
好きなところにコードを追加してください

```java:app/views/tweets/index.html.erb
  
<div class="tweets-container">
  <% @tweets.each do |t| %>
    <div class="tweet">
        <%= t.user.email %>
        <%= t.body %>
        <%= t.created_at %>
        <%= link_to "詳細へ", tweet_path(t.id) %>
       <% if user_signed_in? && current_user.id == t.user_id %>  
         <%= link_to "編集する", edit_tweet_path(t.id) %>
         <%= button_to "削除する", tweet_path(t.id), method: :delete %>
       <% elsif user_signed_in? && current_user.admin? && current_user.id == t.user_id  %>  
         <%= link_to "編集する", edit_tweet_path(t.id) %>
         <%= button_to "削除する", tweet_path(t.id), method: :delete %>
　　    <% end %> 　
        <% if current_user.admin? %>
         <%= link_to "管理者が削除するよ", tweet_path(t.id), method: :delete %>
        <% end %>
    </div>
  <% end %>
</div>

```

# おわりに
わたしは以上のコードで実装しましたが、ところどころ書かなくてもいい場所もあるかもしれません😭
あくまでも参考例ですので、ご自身で足りないところ足りてるところを試行錯誤していただけると助かります。
間違い等もございましたらコメントで教えていただけるとうれしいです！
よろしくお願いいたします

#参考サイト
[【初心者向け】管理者ユーザーと管理者用controllerの追加方法[Ruby, Rails]](https://qiita.com/tanutanu/items/7ce8826615f1af605164)
[投稿の削除を投稿者と管理者どちらからもできるようにしたいです。](https://teratail.com/questions/248863)
JavaScriptのホイスティングって何者？？

# はじめに
初学者です。
ホイスティングについて学んだので備忘録を残します。

# ホイスティングってなに？
コンテキスト内で宣言した変数や関数の定義を**コード実行前にメモリに配置すること**
**宣言の巻き上げ**ともよばれる

宣言した関数よりも前でその関数を呼び出しても実行できますよね。
それです

# いろんなケースのコードを見ていこう
関数

```JavaScript
a();

function a() {
  console.log('a is called')
//関数の定義が実行より後でもホイスティングによって実行可能になる
}
```

var

```javaScript
console.log(b); //処理結果 undefined
var b = 0; //

// この場合のホイスティングは
//変数bのメモリースペースを確保し値に特殊な値(undefined)を設定
```

let・const

```javascript
console.log(b); //処理結果 エラー
let b = 0; //
//letやconstはホイスティングで初期化(undefined)されない
//挙動が違うためvarの使用は非推奨である
```

**ここで一度整理したい**

ホイスティングが行われることによって関数宣言よりも前で宣言した関数を呼び出しても使える
これはJavaScriptエンジンがコンテキストを生成した際に変数や関数を発見しコード実行前にメモリに配置するからである。
変数(定数)の定義にはvar/let/constがあるが、varとlet+constの挙動には違いがある。
変数宣言よりも前でその変数を参照した場合
varの場合は変数をメモリに配置し、値にundefinedを代入する挙動
let+constの場合はホイスティングが行われずにエラーになる（厳密には行われているらしいがエラーがでる）
このようにvarとlet+constには挙動の違いがある。これはホイスティングだけではなく、ブロックスコープの生成の有無など
その他の面でも挙動に違いがある。これらを理由に現在varを使うのは非推奨である


# ホイスティングが発生するタイミングはコンテキストが生成される瞬間
```javascript
function a() {
  console.log(z)
  let z = 1;
}
//関数aの中身は記述の順番が間違っているが、呼び出していないため
//関数aのコンテキストは生成されていない
//関数aのコンテキストが生成された瞬間ホイスティングが発生しエラー
//になる(関数aを呼び出すとエラー)
```
関数式

```javascript
a();

const a = function() {
  let c = 1;
  console.log(c)
} 
//処理結果:エラー
//関数式は変数の宣言と同じ挙動をするため関数宣言と異なり
//宣言より前で呼び出すとエラーになる
```

**コンテキストが生成されるたびにホイスティングが発生し宣言部がメモリースペースに配置される**

# まとめ
コンテキストが生成された瞬間にホイスティングが発生する
ホイスティングによって関数や変数がコード実行前にメモリに保存される
メモリに保存してからコードを実行するため関数はどこからでも呼び出すことができる
ホイスティングの発生はコンテキストが生成されたタイミングなので、関数スコープ内で記述が間違っていても
呼び出していなければホイスティングは行われない。
liff.init は Vue の createApp より前で実行しよう

# 前提
Vue.js (3.x 系)で liff アプリを作成するとき、以下のように `liff.init` していました。


```vue:RootPage.vue
<template>
  <router-view />
</template>

<script lang="ts">
import liff from '@line/liff/dist/lib';
import { defineComponent, onMounted } from 'vue';
import { useRouter } from 'vue-router';

export default defineComponent({
  name: 'RootPage',
  setup() {
    const router = useRouter();

    onMounted(async () => {
      await liff.init({ liffId: 'xxxxxxxxx' });

      if (!liff.isLoggedIn()) {
        await router.push({
          name: 'page1',
        });

      } else {
        await router.push({
          name: 'page2',
        });
      }
    });
  },
});
</script>
```

通常の動作はこれで問題ありませんが、**クエリパラメータを付与して liff アプリに遷移したとき**に問題が起こりました。

# 期待していた遷移の挙動
まず liff アプリに下記のようにクエリパラメータを付与してアクセスします。

```
https://liff.line.me/xxxxxxxxxxxxx?hoge=hoge&fuga=fuga
```

すると、liff サーバによってエンドポイントに指定していたアドレスにリダイレクトされます。この時、もともと付与されていたクエリパラメータは URL エンコードされた状態で `liff.state` というパラメータ内に保持されます。これは、liff アプリにおける**１次リダイレクト**に相当します。（詳細は[公式ドキュメント](https://developers.line.biz/ja/docs/liff/opening-liff-app/#redirect-flow)を参照してください。）


```
https://myliffapp.com/index.html?liff.state=%3Fhoge%3Dhoge%26fuga%3Dfuga
```

その後、Vue が起動し、前述した `liff.init` が呼ばれます。このとき、内部的に`liff.state`パラメータを通常のクエリパラメータとして再解釈した URL にリダイレクトされます。これが、**２次リダイレクト**に相当するものです。

```
https://myliffapp.com/index.html?hoge=hoge&fuga=fuga
```

# 実際の挙動
実際には`liff.init`の後、下記のような URL に遷移されてしまいました。

```
https://myliffapp.com/index.html?hoge
```

なぜか第１パラメータの hoge のキーだけが残る謎挙動。頭を抱えました。

# 仮説
**VueRouter と `liff.init` の両方がパスを管理しようとして衝突しているのではないか、** という仮説を立てました。。
[ドキュメント](https://developers.line.biz/ja/docs/liff/opening-liff-app/#redirect-flow)にも下記のように記載があります。

> liff.init()メソッドが返すPromiseオブジェクトがresolveする前に、サーバーやフロントエンド側の処理などでURLを変更しないようにしてください。

この仮説に基づき、VueRouter が動作し始める前に`liff.init` してみました。

# 結果
下記のように変更したところ、クエリパラメータが期待通りに取れるようになりました。

```ts:main.ts
import liff from '@line/liff/dist/lib';
import { createApp } from 'vue';

import App from './App.vue';
import router from './router';

async function main() {

  // VueRouter が動き始める前に liff.init する
  await liff.init({ liffId: 'xxxxxxxx' });

  const app = createApp(App);
  app.use(router);
  app.mount('#app');
}

main();
```

```vue:RootPage.vue
<template>
  <router-view />
</template>

<script lang="ts">
import liff from '@line/liff/dist/lib';
import { defineComponent, onMounted } from 'vue';
import { useRouter } from 'vue-router';

export default defineComponent({
  name: 'Base',
  setup() {
    const router = useRouter();

    onMounted(async () => {
      // ここでは liff.init しない！！
      // await liff.init({ liffId: 'xxxxxxxxx' });

      // この時点で正しく２次リダイレクトされ、クエリパラメータは正常に読み取れる。

      if (!liff.isLoggedIn()) {
        await router.push({
          name: 'page1',
        });

      } else {
        await router.push({
          name: 'page2',
        });
      }
    });
  },
});
</script>
```

# まとめ
ネット上では `onMounted` 内で `liff.init` している例が散見されるので、同じ部分でハマっている方も多い気がします。react など他のフレームワークでも同様にパスの制御が衝突してしまう可能性があるので、`liff.init`のタイミングには注意したほうがよさそうです。
three.js で glTF データのジオメトリとシェーダを組み合わせる

three.js で blender などで作ったモデルに、
GLSL で記述したシェーダを組み合わせる忘備録です。

## blender 側の設定

blender でモデリングしたデータを glTF 形式で書き出します。
マテリアルのデータが全くないとうまくシェーダが適応されなかった記憶があるので、
エクスポートオプションのジオメトリの「マテリアル」も一緒にエクスポートするようにしてください。

シェイプキーを使う場合は「アニメーション」のシェイプキーにチェックを入れてください。

## three.js

GLTFLoader を使ってデータを読み込み、Mesh のジオメトリデータを取得します。
shader を読み込み、マテリアルデータを作成します。

```ts
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import vertexShader from './shaders/shader.vert';
import fragmentShader from './shaders/shader.frag';

async function getGeometryData() :Promise<THREE.BufferGeometry> {
  return new Promise((resolve) => {
    // gltf の読み込み
    const loader = new GLTFLoader();
    loader.load('./gltf/main.glb', (object) => {
      object.scene.traverse( (child) => {
        // main という名前のオブジェクト
        if(child instanceof THREE.Mesh && child.name === "main") {
          console.log(child.geometry);
          resolve(child.geometry);
        }
      });
    });
  });
}

async function setMesh() {
  const geometry = await getGeometryData();
  const material = new THREE.ShaderMaterial({
    vertexShader: vertexShader,
    fragmentShader: fragmentShader
  });

  const mesh = new THREE.Mesh(
    geometry,
    material
  );
} 
```


## シェイプキーアニメーションを行う場合

blender で作ったモデルデータに、シェイプキーアニメーションを設定し、
アニメーションするオブジェクトに対して shader を利用するときは
VertexShader を下記のようにします。

```c
#include <morphtarget_pars_vertex>

void main() {
  #include <begin_vertex>
  #include <morphtarget_vertex>

  // モデルをローカル座標から視点系座標に変換
  vec4 mvPosition	= modelViewMatrix * vec4( transformed, 1.0 );

  gl_Position	= projectionMatrix * mvPosition;
}
```

シェイプアニメーションを適用。

```js
if (mesh.morphTargetInfluences) {
  mesh.morphTargetInfluences[0] = 1;
}
```
dockerでCodeceptJS3.0.7実行環境を構築する

# dockerでCodeceptJS実行環境を構築する

## 完成品
https://github.com/akasatati/codeceptjs_docker

動作環境
macOS Catalina 10.15.7
docker-compose version 1.29.2

## 使い方
```
git clone git@github.com:akasatati/codeceptjs_docker.git

cd codeceptjs_docker

# 設定ファイル準備
cp .env.example .env
cp conf/environments.example.js conf/environments.js

# buildします
docker-compose build

# お試し実行(yahooでCodeceptJSを検索するテストが走ります)
time docker-compose run --rm codeceptjs codeceptjs run --grep '(?=.*@yahoo)' --steps --verbose
```

## Versionを変更したい場合

.env

```
TZ=Asia/Tokyo
// こちら↓を変更して再度 docker-compose build してください
CODECEPTJS_VERSION=3.0.7
YAHOO_URL=https://www.yahoo.co.jp/
CODECEPTJS_URL=https://codecept.io/
```

## docker imageについて
CodeceptJS公式のdocker imageがあるので、そちらを利用しています。

https://hub.docker.com/r/codeceptjs/codeceptjs/tags
HEBI X-Seriesことはじめ

# はじめに
HEBI X-Series（以下HEBIモータ）はモータ，ドライバ，エンコーダが一つの筐体に収まったスマートアクチュエータです．
使ってみると便利だし公式ドキュメントは充実しているのですが，日本語資料が少ないので，公式ドキュメント噛み砕いていくような立ち位置で記します．

# 目標
HEBIScopeを使ってHEBIモータを動かす．

# 使うもの
- PC
- Ubuntu（筆者の環境はUbuntu 18.04）
- HEBIモータ
- 電源
- 電源ケーブル
- Ethernetハブ
- Ethernetケーブル

# 全体構成
![Screenshot from 2021-10-11 14-38-42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329116/678ae788-6495-5f7f-303f-61c9b4a5b10e.png)

# ネットワークの確認
HEBIモータは同じネットワーク内の端末から遠隔で操作することができますが，この際，Ethernetハブを挟む必要があることに注意が必要です．
（PCのEthernet端子に直接繋いでも認識されません．）
PCは同一のネットワークにいればいいので，WiFiで接続されていてもOKです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329116/935c0247-829f-f00a-ea0d-b75b63e6656e.png)

同一ネットワークにHEBIモータがいるかどうかは，HEBI Scopeを使うことで簡単に確認できます．
![Screenshot from 2021-10-11 14-20-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329116/6603b285-c503-da87-f524-233e1fc6e356.png)
繋いでいるはずなのに表示されない場合は，次のことを確認してください．

- HEBIモータに電源が供給されているか
- Ethernetハブを正しく挟んでいるか
- HEBI Scopeを起動し直す
- WiFiで接続している場合は有線LANで接続する
- PCを再起動する

それでも解決しなければ，PCか施設のネットワーク環境に問題がないか確認してください．

# 初期設定
HEBIモータはそれぞれにNameを割り当てたり，いくつかのHEBIモータをまとめてFamilyとしてグルーピングすることができます．
このNameやFamilyの単位で操作していくことになります．
これらは，HEBI Scopeのモータ名を右クリックし，set nameまたはset familyから設定することができます．

# 動かしてみる
動かしたいHEBIモータを選択してHEBI ScopeのMonitoringタブへと移り，下部の「Position」「Velocity」「Effort」のいずれかにチェックを入れた状態でスライダを動かすことで，それぞれの値を制御し，HEBIモータを動かすことができるはずです．
複数の制御にチェックを入れることで，同時に制御することもできます．

# 動かすことができたら・・・
次はC++やROSで動かしてみましょう．
より複雑な動きや，ロボットへの実装が可能になります．
[公式ドキュメント](https://docs.hebi.us/tools.html)を参考にプログラムを組んでみてください．