OmniAICreator/Qiita-1.07M huggingface dataset:
Git 取り消し（ワークツリー・ステージ・コミット毎）


Every Qiita #25
のんびり独学初学者投稿 25日目
今回は・・・
gitの変更の取り消し（ワークツリー・ステージ・コミット毎）を再度整理した時の備忘録です。

### 各階層毎の取り消し一覧
####ワークツリーの変更を取り消す（git addする前)
コマンド：`git checkout -- <ディレクトリ名　または　ファイル名> または <.(全て)>`
内容：ワークツリーの変更を取り消す　**※直前のステージ内容をワークツリーに反映する**
備考：ステージに上がっていない（直前でコミットまで完了している）場合は取り消しできない。

####ステージの変更を取り消す(git commitする前)
コマンド：`git reset HEAD <ディレクトリ名　または　ファイル名> または <.(全て)>`
内容：ステージの変更を取り消す 　**※直前のコミット内容をステージに反映する**
備考：ワークツリーには反映されない


####コミットの変更を取り消す(git pushする前)
コマンド：`git commit -- amend`
内容：コミットの内容を取り消す（上書きする） **※直前のコミット内容を現在のコミット内容で上書きする**
備考：取り消すのではなく、新たにコミットする内容で上書きする
**※pushした後の変更はしない（リモートリポジトリの内容とローカルリポジトリのコミット状態が変わるため）**

####git pushした内容を取り消す
pushした後に内容を取り消したい場合はローカルリポジトリで変更し、再度pushする。
**push自体を取り消すのは履歴が変わってしまい、コンフリクトの可能性が出るためオススメしない**

###参考資料（有料)
https://www.udemy.com/course/unscared_git/
AWS認定試験のTips

ソリューションアーキテクト　プロフェッショナル試験の更新を済ませてきました。
前回の更新を忘れていて、アソシエイトから受け直すことになったので、今回は忘れぬうちに！

試験においての自分流Tipsを共有しておきます。
誰かのお役に立てればこれ幸い :)

## 英語に切り替える

読みにくい日本語は英語に切り替えるとわかりやすいことも。

とくに、複数選択問題。
例えば、「2つ選びなさい」という問題の場合、
AとBを両方行うことで実現できるパターンと、
AでもBでもどちらでもできるパターン、どちらも考えられる。

前者の場合、「Combination」と書いているので、明確に判断がつく。


## 理解の浅いサービスに関する問題が出たら、サービス名と問題番号をメモる
試験内の別問題で、そのサービスが含まれる問題が出てくることもあります。
その問題が、大きなヒントになることも結構あります。
合わせて読むと、さっき不明確だったことが、別の問題で明確になることも。

## 途中での想定算時間を割り出す
プロフェッショナル試験の場合、問題数75問、試験時間180分と長丁場。
最初に、ざっくりと途中時点での想定算時間を書いておくと、大幅な時間不足を防げる。
例えば、プロフェッショナル試験だと、25問の時点で残り１２０分、50問の時点で残り6０分が等分のペース。
これを下回るペースだと少し急いだ方がいいかも。
見直しを考える人は、25問の時点で残り１3０分、50問の時点で残り8０分のペースで進め、見直しに30分残すとか。
ペース配分は個人によるので、適宜チューニングになりますが、試験開始前または早いうちに時間見積もりを立てて、途中経過を観測することをオススメ。

## 図を描く
※  オンラインではできないらしい
とくにプロフェッショナル試験は問題が長く、構成の説明だけで１０行ぐらい続くことも。
図に描くことで、長々とした説明を視覚的に捉えて、問題文で問われていることに集中できる気が。
Laravelから受け取ったデータをVueで非同期で更新する。

###はじめに

LaravelからVueにデータを渡すときのメモを大まかに書いておきます。


環境
Laravel  8.33.1
vue: 2.5.17

<br/>

api.phpに書くのが正しいのかweb.phpに書くのがいいのかわからないのですが、どちらでも動く、違いといえばapi/をつけるかどうかくらいにしか理解できていないです。。
<br/>

web.php

```php
 Route::get('/', [ProductController::class,'index']);
 Route::get('/Products', [ProductController::class,'getProducts']);
```


<br/>

テーブル

```php
  $table->id();
  $table->string('name');
  $table->string('description');
  $table->timestamps();
```
<br/>
Resourceをつくって必要なデータだけを取り出します。

```
php artisan make:resource ProductResource
```



<br/>
Resourceを書き換え。timestampsは必要ないので取り除いてる。

```php
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->word,
            'description' => $this->description,
        ];
        //デフォルト↓
        // return parent::toArray($request);
    }
```

<br/>

ProductController

```php
    
   //useを追加
   use App\Models\Product;
   use App\Http\Resources\ProductResource;
    
    //viewを返す
    public function index()
    {
        return view('index');
    }
    
    //Vueにデータを渡す
    public function getProducts()
    {
    return ProductResource::collection(Product::all());

    }

```


<br/>
View。appで囲む。script を忘れずに書く

```html
     <div id="app">
        <product-page/>
    </div>

    <script src="{{ asset('js/app.js') }}"></script>

```


<br/>
Laravelからのデータをaxiosで受け取る。受け取ったデータを空の配列のproductsに入れる。for文で回す

```vue
 <template>
  <div >
      <p v-for="product in products" :key='product.id'>
      {{ product.name}}
　　　 {{ product.description}}
       </p>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      products: [],
    };
  },
  mounted() {
    this.loadEnglishWord();
  },
  methods: {
//Laravelからのデータをaxiosで受け取る
    loadProducts: function () {
      axios
        .get("/products")
        .then((response) => {
          //  console.log( response)
          this.products= response.data.data;
        })
        .catch(function (error) {
          console.log(error);
        });
    },
  },
};
</script>

```
【Rails】rails sのログに表示される「Cannot render console from <IPアドレス>!」とは何か？

#はじめに
dockerを使って、localhostで立ち上げたときに、rails server上で以下のようなログが発生。

```
web_1  |Cannot render console from 172.23.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
```


#結論
#####「docker のネットワークで使っているIPアドレス(172.23.0.1)がループバックの範囲(127.0.0.0～127.255.255.255)にないから、表示できないよ」
↓
#####「environment/development.rbに追記して、docker のネットワークで使っているIPアドレス(172.23.0.1)を許可しなければならないよ」

#詳細
アウトラインはこちらの方の記事を参考に。
https://qiita.com/terufumi1122/items/73da039e6fc90ee0a63f


#####※補足「networks: 127.0.0.0/127.255.255.255」とは？
【ループバックアドレスの範囲】を指すようです。

ちなみに、「ループバックアドレス」とは自分自身を示す仮想的なIPアドレスです。
（例えば"localhost/3000" と "127.0.0.1/3000"はおおよそ等価と考えてよさそうです。）

「ループバックアドレスは一般的に127.0.0.1が指定されているけど、
状況次第で127.0.0.0～127.255.255.255の範囲で別のアドレスも設定できるよ」ということです。
詳しくは以下の記事で。

http://atnetwork.info/tcpip/tcpip57.html

#おわりに
簡単ですが、以上です。
どなたかの参考になれば幸いです。
Google ドライブから大量のファイルを削除する

## Google ドライブのルートから大量のファイルを削除する

【注意】
この記事はGoogle Drive上のファイル削除に関するものです。
誤って必要なファイルを消してしまわないよう、実行には充分注意してください。

### どうしてこうなった
Google Colab用に動画から学習用のデータを切り出そうとして、Google ドライブのルートに大量（数万件）のファイルを吐き出してしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/f8607469-b9d3-5abf-2ea5-4d1b18c38c80.png)

Colabでもう一度マウントして消そうと思ったのですが、ファイルが大量にあるとタイムアウトするんですね…。

↓やらかした人しか見られないマウントのタイムアウト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/69be3214-7ddc-6cf9-0783-3c1f5aecb6e0.png)


### 解決策

流石に手作業ではつらすぎるので、GASの助けを借りて削除することにしました。

GoogleDriveの画面から「新規」→「その他」→「 Google Apps Script」を開きます

![gas_open.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/9b1cb467-9554-2b1b-578d-e83c62793499.png)

こんな感じでエディタ画面が開きます

![gas_editor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/cfcbac7a-e8dc-6cc3-214d-2746334f65c3.png)

エディタ画面に以下のスクリプトを貼り付けて保存（Ctrl + S）

```javascript
function myFunction() {
  // ルートフォルダを取得
  var folder = DriveApp.getRootFolder()
  // ルートフォルダからjpeg形式のファイルだけを抽出
  var files = folder.getFilesByType("image/jpeg");

  var delCount = 0
  while (files.hasNext()) {
    var buff = files.next();
    var fileName = buff.getName()
    // 誤削除が怖いので念のためファイル名の先頭を確認
    if (fileName.startsWith("IMG_")) {
      delCount++
      var fileId = buff.getId()
      const file = DriveApp.getFileById(fileId);
      file.setTrashed(true); // ゴミ箱に移動
      Logger.log(`count:${delCount}, file: ${fileName}`);
    };
  };
}
```

保存が完了すると上段の実行ボタンが押せるようになるので、ボタンを押して実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/905a8656-eb7d-af09-bafb-67cf1c05c198.png)

「権限よこせ」と言われるので「権限を確認」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/1ea9c275-b089-049a-dcbb-691658b59b6f.png)

怖めの警告が出ますが、自分で作ったものなので「詳細」から許可します
※当たり前ですが、自己責任でお願いしますね
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/cd2c9f25-6170-9b3f-40f3-31d5ebeda766.png)

安全ではないページだそうですが、自己責任で突き進みます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/6ccd25a6-b4ab-25ad-9e65-6ec58a68e89b.png)

内容を確認して「許可」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/7b13a480-e08f-c751-0ac3-ab5df7fe93d3.png)

権限を与えると、こんな感じで削除されていきます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/f3c9657b-3df2-0d50-d74d-b73107a1ff8a.png)


Google Driveからゴミ箱を確認するとガンガン増えていってるので、時々空にしながら完了を待ちます。
GASは実行時間に制限があるようなので定期的に再実行しなければなりませんが、手作業よりだいぶ楽になりました。

![trash.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1649366/bbd6484f-348c-a3a0-af2d-17a2968ee791.png)
Swiftのinit(イニシャライザ)のオーバーロードはconvenienceで行う

# initのオーバーロード

Swiftでのinit(イニシャライザ)のオーバーロードはほかの言語とは子なり、少し特殊です。
Swiftでは`convenience`を使用することで、オーバーロードが可能です。

```swift
class Alert {
    var title : String
    var message : String
    var level : Int

    init(title : String, message : String, level : Int) {
        self.title = title
        self.message = message
        self.level = level
    }

    convenience init(title: String) {
        let message = "デフォルト"
        let level = 0

        self.init(title : title, message : message, level : level)
    }

    convenience init(message: String) {
        let title = "デフォルト"
        let level = 0

        self.init(title : title, message : message, level : level)
    }

    func show() {
        print("\(self.title) \(self.message) \(self.level)")
    }
}

let alert1 = Alert(title: "title", message : "Hello", level : 1)
let alert2 = Alert(title: "タイトル")
let alert3 = Alert(message : "メッセージ")

alert1.show()
alert2.show()
alert3.show()
```
【初心者向け】Rubyでコマンドラインツールを作る

hello.rb というファイルを作ってみてください
中身は `puts "world"`  です
これを ruby hello.rb で実行してみてください

```
% ruby hello.rb
world
```

となりますね。

そうしたら

```ruby
#!/usr/bin/env ruby
puts "world"
```

に変更してくてみださい。
ファイル名も hello.rb から hello に変更します。

`./hello` で実行してみましょう。

```bash
% ./hello
-bash: ./hello: Permission denied
```

このようなエラーが出ます。
実行する権限がないので追加します。

```bash
% chmod +x ./hello
```

再実行します。

```bash
% ./hello
world
```

おわりです。
指定時間が経過するとブックを強制終了するマクロ

## 背景
社内で複数名で使う共有ブックを**誰かが使用中で保存できない問題**の対策を考えた。

ブックの共同編集を許可する手もあるが、サーバ上のExcelファイルはスプシやTeams上と違って相手の操作状況がわからないため、データベース系ブックでキーの重複やデータの齟齬が発生する危険がある。

誰かが開きっぱなしで放置している場合はもう**モラルで何とかするしかない**と思われていたが、`Application.OnTime`メソッドなる**遅延実行メソッド**があることを知り、一瞬で解決した。

あとは編集中の一時ファイルを別ブックに保存するとかの味付けをするかしないかくらい。


## 設定方法と使用方法

編集可能時間をh,m,sで設定。
下記では3分。

3分経過するとmsgboxが表示され、10秒後に自動的に閉じる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281933/b514e1a0-77de-fa45-70f3-a68214cf1147.png)

ここで「はい」を押すと**再度3分の編集時間を与えられる。**
このポップが出ている間に繰り返せば編集を続けられるが、**放置されたら強制終了する。**


## 標準モジュール
``` vb
Option Explicit

Sub 指定時間経過で強制Close()
  Dim h, m, s
  h = 0
  m = 3
  s = 0
  
  Application.OnTime _
    Now + TimeSerial(h, m, s), _
    "'msg ""時間ですよ""'"
End Sub

Sub msg(ByVal strMsg As String)
  ThisWorkbook.Activate
  Beep
  If Judge(strMsg, 10) = False Then
    ThisWorkbook.Close
  Else
    Call 指定時間経過で強制Close
  End If
End Sub

Private Function Judge(Title, s) As Boolean
  Dim flg As Boolean
  Dim WSH As Object
  Set WSH = CreateObject("WScript.Shell")
  
  Dim prompt
  prompt = "制限時間になりました。" & vbLf & _
           "延長する場合は「はい」を押してください。" & vbLf & vbLf & _
            "※" & s & "秒後、自動的に閉じます。" & vbLf & _
            "その際、保存されていないデータは破棄されます。"

  Dim rc
  rc = WSH.Popup(prompt, s, Title, vbYesNo)
  If rc = vbYes Then
    flg = True
  Else
    flg = False
  End If
  Set WSH = Nothing
  
  Judge = flg
End Function

```

## ThisWorkbookモジュール
``` vb
Option Explicit

Private Sub Workbook_Open()
  Call 指定時間経過で強制Close
End Sub
```


## 参考

http://officetanaka.net/excel/vba/tips/tips21.htm

https://vbabeginner.net/ontime/

呼び出すプロシージャ名は`"`で囲むことになっており、
さらに`'`で囲み、半角スペースの後に`""`で引数を与えることもできるらしい。
（今回、無理に引数を使う必要はなかったがメモとして残しておいた。）

``` vb:指定時間経過で強制Close
  Application.OnTime _
    Now + TimeSerial(h, m, s), _
    "'msg ""時間ですよ""'"
```

↓呼ぶプロシージャ

``` vb
Sub msg(ByVal strMsg As String)
```

https://excel-ubara.com/excelvba1/EXCELVBA420.html
Teensyduinoのコンパイルができない時の対処法

#Teensy4.0をTeensyduinoで開発したい
(2021/7/30時点の情報です)
Teensyの開発環境の導入でつまづいたので備忘録として

###症状
ArduinoでTeensyを開発する際には[Teensyduino](https://www.pjrc.com/teensy/teensyduino.html)というソフトが準備されています。
しかしこれがMacもWinもそのままではコンパイル時に
panic: no patch version found
というエラーが表示されてしまいコンパイルできませんでした。

###解決方法
Arduino IDEが1.8.15ではできませんでした。
初めにWindowsでは1.8.12にして動作、Macbook Air(M1)では1.8.13で動作を確認しました。
Macでは単体のボードプロファイルではなく、Teensyduino IDEのパッケージで配布されているので、
アプリケーションのTeensyduinoを右クリックしてパッケージの中身を表示させて
Contents/Java/hardware の中にあるteensyフォルダ、toolsフォルダの中のavrフォルダ以外のものを
Arduino IDEのhardwareフォルダにコピーすることで動作を確認できました。

なぜそれが起きたのかまではわかりませんが、とりあえず解決したので
少ない日本語情報として残しておきます。
BigQueryで特定の列による重複判定で行を削除

# はじめに
データベースも知らないよちよち歩きでBigQueryに触り始めたので、今後やりたいことの備忘録がてらTipsを共有していきます。
SQL自体も勉強しながらやりくりしていますので有識者様のマサカリを歓迎します。

# やりたいこと
下図のように日付とセンサ値、その他情報が入ったテーブルがあるとします。
![00 table2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131278/d33dc4a1-b691-7289-26e9-b7c9f222d0f5.png)
使用しているIoTセンサがチープなもので、同じ時刻で異なる情報が送られてくる仕様を想像してください。
今後の集計作業に邪魔になるため、日付の重複を検知してその行を削除するような前処理の実装を考えます。
※ 行1, 2と行5, 6がそれぞれ今回の重複判定対象となります。

# 重複判定処理
## 単純な列指定
```sql
SELECT DISTINCT insertDatetime
FROM `project.dataset.table`
ORDER BY insertDatetime;
```
![01 simple select distinct.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131278/4c6ced4e-7e99-93c4-178b-48d4d0d9043c.png)
まずは一番単純な `DISTINCT column_name` です。
重複判定に用いるカラム名を指定すれば日付の重複は確かに消えていますが、他に参照したいセンサ値たちが取れていません。

## 取得したい列全てを指定
```sql
SELECT DISTINCT * 
FROM `project.dataset.table`
ORDER BY insertDatetime;
```
![02 select distinct all.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131278/110c2ff3-957d-ebc2-9011-0d62ade2f22d.png)
取得したいのは全てのカラムなので、今度は`DISTICT *`を指定します。
挙動としては`DISTINCT`の対象が全てのカラムになるため、全てのカラムが同じ値である行1が消えました。
惜しいですが、行4も消えてほしいためまだ満足できません。

## 行番号を用いて参照
```sql
WITH indexing AS (SELECT *, ROW_NUMBER() OVER(ORDER BY insertDatetime) AS refId FROM `project.dataset.table`)
SELECT * EXCEPT(refId) FROM indexing
WHERE refId in (SELECT max(refId) FROM indexing GROUP BY insertDatetime)
ORDER BY insertDatetime;
```
![03 row number.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131278/d80de516-5bd9-e555-3d9b-3cc4e555e9de.png)
手間が一気に増えましたが、やったことは「行番号を用いて重複していない行のみを抽出する」というものです。

```sql
WITH indexing AS (SELECT *, ROW_NUMBER() OVER(ORDER BY insertDatetime) AS refId FROM `project.dataset.table`)
```

`refId`という行番号を示す列を新たに作成します。
`WITH`を用いて元のデータと行番号列を一時保存しておきます。
(`WITH`でできるものは何なのでしょうか……  共通テーブル?一時テーブル?ビュー?)

```sql
SELECT * EXCEPT(refId) FROM indexing
WHERE refId in (SELECT max(refId) FROM indexing GROUP BY insertDatetime)
ORDER BY insertDatetime;
```
重複対象となる`insertDatetime`を`GROUP BY`で指定し、該当する最大行 (=最新値) をサブクエリで取得します。
古い方を残したい場合は`MIN(refId)`で良いですね。
あとはサブクエリで抽出した行を`WITH`で保存した結果から`SELECT WHERE`で指定すれば、日付が重複する行を除去した全列データが取得できます (`refId`は処理用に設けただけなので`EXCEPT`で除いています) 。
クエリ結果を見ても、行1と行4が消えて欲しい形で参照できていることが分かります。

# 終わりに
MySQLの場合は`DISTINCT ON(column)`で本記事と同じことができるとかなんとか。
リファレンスを読みましたがこれに該当する操作はBigQueryには無さそうだったので情報共有を兼ねて本記事を書きました。
私と同じような初学者の助けになれば幸いです。
もう少しスマートに書けるなら教えてくれると嬉しいです。
YAMAHA RTXルーターのIPv6(IPoE接続時)ルーティング設定メモ

# 前書き
YAMAHAのRTXシリーズのルーターでインターネット接続時(IPv6 IPoE)にconfig設定だけでは解決の出来ない諸々のトラブルに遭遇したのでその時の問題解決方法を情報共有のメモをしておきます。
なお基本的にコマンド設定です。Web画面のGUIでは詳細な調整が出来ません。
不具合例を逐次追加更新して置きます。

# インターネット接続環境

- 回線：NTT東日本フレッツ光ネクスト
- ISP：IPv6 IPoE接続(MAP-E)
- ルーター機器：YAMAHA RTX1210

# ネットワーク構成

「インターネット」
　　　↑
「NTT ONU」
　　　↑
「YAMAHA RTX1210 WAN側」(LAN2ポート)
　　　↑
「YAMAHA RTX1210 LAN側」(LAN1ポート)
　　　↑
「端末側」

# IPv6 IPoE 設定

公式の設定事例を参考にします。

https://network.yamaha.com/setting/router_firewall/flets/flets_other_service/ipv6_ipoe


~~~:WAN側の設定
ipv6 prefix 1 ra-prefix@lan2::/64
ipv6 lan2 dhcp service client ir=on
~~~

~~~:LAN側の設定
ipv6 lan1 address ra-prefix@lan2::1/64
ipv6 lan1 rtadv send 1 o_flag=on
ipv6 lan1 dhcp service server
~~~

# IPv6 設定確認コマンド

IPv6の動作確認に使用する以下のコマンドを使用します。

~~~:IPv6アドレス番号の表示
# show ipv6 address
~~~

~~~:IPv6ルーティング表示
# show ipv6 route
~~~

# IPv6アドレスの例

WAN側(LAN2ポート)：ABCD:EF01:2345:6789:ABCD:EF01:2345:6789/64

LAN側はWAN側からRAプレフィックスで上部64bitを取得して下部64bitに1を割り当てます。

LAN側(LAN1ポート)：ABCD:EF01:2345:6789::1/64


# 不具合例１

~~~:IPv6アドレス番号の表示
# show ipv6 address
LAN1 scope-id 1 [up]
 グローバル     ABCD:EF01:2345:6789::1/64 (lifetime: 1234567/1234567)

LAN2 scope-id 2 [up]
 グローバル     ABCD:EF01:2345:6789:ABCD:EF01:2345:6789/64 (lifetime: INFINITY)
~~~

~~~:IPv6ルーティング表示
# show ipv6 route
Destination              Gateway                   Interface  Type
default                  fe80::ABCD:EF01:2345:6789 LAN2       RA
ABCD:EF01:2345:6789::/64 -                         LAN1       implicit
~~~

この状態でもIPv6の疎通は出来ているのですがRTX1210機器本体を再起動すると以下のようになります。LAN側のLAN1ポート側にグローバルが再配置されました。WAN側のLAN2ポート側はリンクローカルfe80::だけになります。

~~~:IPv6アドレス番号の表示
# show ipv6 address
LAN1 scope-id 1 [up]
 グローバル     ABCD:EF01:2345:6789::1/64 (lifetime: 1234567/1234567)
 グローバル     ABCD:EF01:2345:6789:ABCD:EF01:2345:6789/64 (lifetime: INFINITY)
~~~


# 不具合例２

~~~:IPv6ルーティング表示
# show ipv6 route
Destination              Gateway                   Interface  Type
default                  fe80::ABCD:EF01:2345:6789 LAN2       RA
ABCD:EF01:2345:6789::/64 -                         LAN2       implicit
~~~

これはWAN側であるLAN2ポート側にルーティングされてしまった状態。
RTX1210からはIPv6疎通しますがLAN側であるLAN1ポート側に接続された端末側からはIPv6インターネットに接続出来ません。
また、RTX1210機器本体を再起動しても不具合は解消されませんでした。
LAN側のIPv6割当を一旦解除して再設定する事で不具合は解消しました。

~~~:LAN1ポート側を再設定
no ipv6 lan1 address ra-prefix@lan2::1/64
ipv6 lan1 address ra-prefix@lan2::1/64
~~~


# 不具合例３

~~~:IPv6ルーティング表示
# show ipv6 route
Destination              Gateway                   Interface  Type
default                  fe80::ABCD:EF01:2345:6789 LAN2       RA
2345:6789:ABCD:EF01:ABCD:EF01:2345:6789/128 -                         LAN2       implicit
ABCD:EF01:2345:6789::/64 -                         LAN1       implicit
~~~

2回線のマルチホーミング環境であった不具合で別のIPv6サブネットが割り振らてしまった状態。LAN側から別のIPv6サブネットが到達しない様にフィルター等で調整します。
#3 SinatraでActiveRecordを使わずに掲示板アプリを作ってみた

[前回](https://qiita.com/divclass123/items/290cd5d47c03dc73e60e)の続き。
前回はモデルを見て行ったので、今回はdatabaseディレクトリ を見ていく！

# create_database.sql

ここにデータベースやテーブル作成のSQLを書いてくっぽいけど、どんなコマンドを実行したら
データベースが作られるのかは全く分からない。そこからイメージがついてない。
てか、ここにSQL文書いても、まずデータベースに接続ができるのかが怪しい。
確かにクライアントは定義したけど、別のディレクトリのファイルに定義したから
それをどう連携させるのか。include db.rbとかするわけでもなさそうだし。
一旦、そこは飛ばしてどんなコードか理解していくとする

```sql
CREATE DATABASE IF NOT EXISTS 0ch;
```

まぁこれはそのままで、Ochって名前のデータベースがなければ、
そのデータベースを作るって感じです。
next!

# create_post.sql

```sql
CREATE TABLE IF NOT EXISTS posts (
  id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
  topic_id INTEGER UNSIGNED NOT NULL,
  name VARCHAR(255),
  email VARCHAR(255),
  body TEXT NOT NULL,
  created_at DATETIME NOT NULL,
  PRIMARY KEY (id)
);

```


IDカラムのデータ型はINTEGERで数値が入っていく

```
UNSIGNED AUTO_INCREMENT
```

は、https://kin-memo.hatenablog.com/entry/2018/02/07/182952
この記事にある通りで
UNSIGNEDは、正の数値のみ受け付ける感じ。
AUTO_INCREMENTはその名の通り。
レコードが追加されると、自動的に付与される。今回付与されるのはid
レコードが追加されるたび、idカラムにインクリメントされた数値が追加されていく。


NOT NULLはその名の通り、このカラムには絶対何かしらの値が入っていなきゃいけない。といった制約。


topic_idがなぜあるかというと、
一つのトピックに、いくつもの投稿が紐ずくので、
どのトピックに対する投稿かを識別できるように、
外部キーを設定する必要がある。


https://www.dbonline.jp/mysql/table/index8.html 
>PRIMARY KEY(主キー)とは作成したテーブルの中の1つまたは複数のカラムの組み合わせに対して設定するもので、テーブルに格納されているデータをに格納されているデータを識別するための目印のようなものです。

まぁ確かにプライマリーキーがあれば、id=3でそのデータが参照できるってわけか。
プライマリーキーに指定したカラムは重複とNULLを受け付けないようになる。
受け付けたら識別できなくなるからね

てか、railsで開発してた頃は、プライマリキーを指定した覚えなんてないんだが、、
それなのに困ったことなかった。。。。なんでやねん。。。
sinatraとrailsを行き来すれば、理解深まりそうと思った。
railsの仕組みについても興味が湧いてきますね。




# create_topics.sql

```sql
CREATE TABLE IF NOT EXISTS topics (
  id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,
  title VARCHAR(255) NOT NULL,
  created_at DATETIME NOT NULL,
  updated_at DATETIME NOT NULL,
  PRIMARY KEY (id)
);
```

まぁ、さっき解説した通りですね〜。


# app.rb

ついでにapp.rbも見ておきましょう。

```ruby

require 'sinatra'
require 'slim'

require_relative 'models/topic'
require_relative 'models/post'

get '/' do
  @topics = Topic.all
  slim :index
end

post '/topics' do
  topic = Topic.new(title: params[:title])
  topic.save
  redirect '/'
end

get '/topics/:id' do
  @topic = Topic.find(params[:id])
  @posts = Post.of_topic(@topic.id)
  slim :show
end

post '/topics/:topic_id/posts' do
  name = params[:name].empty? ? '名無し' : params[:name]
  post = Post.new(name: name, email: params[:email], body: params[:body], topic_id: params[:topic_id])
  post.save
  redirect back
end
```

なんだかroutes.rbみたい

まぁ、なんとなくわかるので、大丈夫でしょう。

次回はいよいよ、アプリを実行していきたいと思います。
コードを書いたはいいけど、何のコマンドを打てば
データベース作られたりするのかがいまいちよく分からないですね。

# [#4はこちら](https://qiita.com/divclass123/items/467de63fb33a9ae22d33)
【PHP】配列から一つのカラムを取り出す、及びキー名をカラム名にする

```PHP
<?php
$rows = [
    0 => [ 'id' => 10, 'language' => 'PHP',        'ｆramework' => 'Laravel'],
    1 => [ 'id' => 20, 'language' => 'Java',       'ｆramework' => 'Spring'],
    2 => [ 'id' => 30, 'language' => 'JavaScript', 'ｆramework' => 'Vue.js' ],
    3 => [ 'id' => 40, 'language' => 'Ruby',       'ｆramework' => 'Ruby on Rails' ]
];
$abc = array_column($rows, 'language', 'id');

var_dump($abc);

?>
```

もしくは

```PHP
<?php

$array = [
    0 => [ 'id' => 10, 'language' => 'PHP',        'ｆramework' => 'Laravel'],
    1 => [ 'id' => 20, 'language' => 'Java',       'ｆramework' => 'Spring'],
    2 => [ 'id' => 30, 'language' => 'JavaScript', 'ｆramework' => 'Vue.js' ],
    3 => [ 'id' => 40, 'language' => 'Ruby',       'ｆramework' => 'Ruby on Rails' ]
];


foreach($array as $list){
    $data[$list['id']] = $list;
    unset($data[$list['id']]['id']);
}

var_dump($data);
?>
```

#出力結果

```
array(4) {
  [10]=>
  string(3) "PHP"
  [20]=>
  string(4) "Java"
  [30]=>
  string(10) "JavaScript"
  [40]=>
  string(4) "Ruby"
}
```
mixhostでLaravelアプリをデプロイした時のメモ

mixhostはPHPに対応しているWebサーバーであるのでLaravlやWordpressのアプリケーションを公開することができる。今回はLaravelアプリを公開してみた。
###フロー
1.サブドメインの作成
2.Gitcloneでプロジェクトをインポートする
3.composer install
4..envの記述の変更
5.マイグレーション
6.シンボリックリンクの作成

##サブドメインの作成
mixhostのCパネルからサブドメインを作成する。
名前は公開したいLaravelのアプリケーション名なるようにする。
##Gitcloneでプロジェクトをインポートする
SSH接続で該当のmixhostサーバーに接続する。
その後、`cd public_html` で公開ディレクトリにアクセスする。
そのディレクトリでgit cloneでプロジェクトをインポートした。
作成したサブドメインにアクセスして、Laravelのアプリケーションにアクセスするようにしたいのでmvコマンドでディレクトリの名前を変更した。
なお、サブドメインを作成した際に自動でsubdomainというディレクトリが作成されるので削除するか名前を変更しておくのが良い。
e.g.)Laravelのアプリケーションがtestapp、作成したサブドメインがsubdomainの時

```
$mv testapp subdomain
```
##composer install
該当のLaravelプロジェクト上で `composer install` を行い、Laravelに必要なファイルやライブラリを本番環境のアプリケーションにインポートする。
この際、レンタルサーバーのPHPのバージョンやcomposerをインストールしていない場合はできない可能性があるので気をつける必要がある。

##.envの記述の変更
本番環境用のデータベースに接続するために.envの記述を変更する必要がある。
なお、本番環境のDBにマイグレーションするので、あらかじめレンタルサーバー側でデータベースを作成していく必要がある。

作成後、.envの記述を変更する準備をする。
gitにpushしたLaravelのプロジェクトでは.gitignoreファイル関係上.envはプロジェクト上に存在しないのでcpコマンドでenv.exampleから複製して作成する。

```
cp .env.example .env
```

その後、viコマンドで.envの記述を変更する。

```
APP_NAME=test-app
APP_ENV=production
APP_KEY=
APP_DEBUG=false
APP_URL=https://test-app.test.com
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=localhost
DB_PORT=3306
DB_DATABASE=DB名
DB_USERNAME=DBユーザー名
DB_PASSWORD=DBパスワード
```

次に。artisanコマンドでAPP_KEYを作成する。

```
$ php artisan key:generate
```
キャッシュコマンドで.envの変更を修正することを忘れないようにしてほしい。

##マイグレーション
DBの準備ができたのでマイグレーションを行う。

```
$ php artisan migrate
```
これで本番環境にも利用したいテーブルが反映される。
必要であればダミーデータをシーダーやファクトリから挿入する。

##シンボリックリンクの作成
このまま作成したサブドメインのURLにアクセスしても目的のLaravelのアプリケーションを起動できないので、シンボリックリンクを作成する必要がある。
In -s リンク元のパス リンク先のパス
のように記述する。

e.g)honbanドメインにサブドメインとしてsubdomainを作成した。そこに対して、相対パスでLaravelのpublicディレクトリへとシンボリックリンクを作成した。

```
$ ln -s ~/public_html/subdomain.honban.com /home/testuser/public_html/subdomain/public
```

これでシンボリックリンクも作成できて、実際のサブドメインにアクセスしてもLaravelのアプリケーションを公開することができた。

##参考
https://rtr-x8.com/laravel/post-290/

https://mutimutisan.com/larave-to-mixhost

https://naoya-ono.com/blog/deploy-laravel-xserver/

https://arrown-blog.com/laravel-sakura-deploy/#1Laravel3
ソースコードが売買できるPieceXの使い方


![piece_rogo3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232631/66a9b1ad-e466-dd11-4102-9b602be722c4.jpeg)

#1. PieceXについて

PieceXとは、ソースコードを購入・販売できるプラットフォームです。
今まではプログラミングの際にwebで調べていた方も、PieceXにアクセスすれば良質なソースコードを即時に探すことができます。
また、探すだけでなく、作成したソースコードを販売することも可能です。
作成されたソースコードをご自身が妥当だと思われる金額で売り出します。
たくさんの方にソースコードが買われ、評価や人気度が上昇するたびに最適価格に自動的に価格変動するアルゴリズムが採用されています。
自作のソースコードをマネタイズしたいと考えている方は一度PieceXを使ってみてはいかがでしょうか。

サービス名称： PieceX
ドメイン： https://piecex.com

#2. PieceXのアカウント作成方法

ソースコードを売買するためにはアカウントを作成する必要があります。
PieceXサイトへアクセスします。（https://piecex.com）

![piece_login.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232631/bd5c69c5-f772-3468-0e13-c89ce523addb.jpeg)

トップページ右上の「登録」をクリックします。
必要項目を入力し、「アカウント作成」をクリックします。
アカウント作成をクリックすると、アカウントが作成されます。
Google,Facebook,Githubのアカウントをお持ちの方はそちらでアカウント登録することも可能です。
その後、登録メールアドレス宛にメールが送信されるので、内容を確認し、登録後24時間以内にリンクをクリックして登録は完了です。

#3. PieceXの使い方
アカウントを作ったら早速使用してみましょう。

###3-1.ソースコードを買う

![piece_buy1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232631/817c27e7-1acd-5f76-2f3a-292cad582c1d.jpeg)

欲しいソースコードを探してみましょう。
右上の「ソースコードを買う」をクリックすると様々なソースコードが表示されます。
「ジャンル」、「言語」を選択して、希望のソースコードを見つけます。
その際に並べ替えを使用すると、新着や人気、価格や評価順にできます。
購入したいソースコードは見つかったらカートに追加します。
カート内の購入ボタンをクリックすると支払いの確認があります。
購入後はレビューをすることで評価が変動し価格も変化し、質のいいソースコードになっていきます。

###3-2.ソースコードを売る

![piece_sell1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232631/452b7983-4bbb-e65f-8041-970bddb4c9ed.jpeg)

ご自身が作成したソースコードを販売してみましょう。
投稿する前にチェックリストを参照し、販売コードの条件やお支払いの受領について確認してください。
投稿する際に価格設定がありますが、まずはご自身の希望の金額を設定してください。
その後購入された方のレビュー評価や人気度により価格が変動します。

#4.PieceXのその他機能

###4-1.ニュースレター登録
まずトップページ下部にある「ニュースレター」に登録してみましょう。
最新ソースコードの情報をいち早く手にいれることができます。

###4-2.リクエスト
ご希望のソースコードがみつからなかった場合はリクエストをしてみましょう。
トップページ上部にある「リクエスト」をクリックしてリクエストすることができます。
過去に同じようなリクエストがあった場合はその意見に「いいね」を押すとその数が反映されていきます。
このリクエストを参考にソースコードを作成すると、より多くの方に利用してもらえます。

###4-3.無料ソースコードを使用してみる
ソースコードの売買について説明しましたが、PieceXのサイト内には無料のソースコードもあります。
一切無料ですので様々な用途に役立ててみてください。
この無料ソースコードをよりよく改変して、有料販売することも可能です。

#5.さいごに
今回はPieceXの基本的な機能について紹介しました。
最後まで読んでいただいた方、ありがとうございました。
argparseで、コマンドライン引数の値が格納されない時の対応

コマンドライン引数から、 python test.py --box ok　と入力し、
boxにokを渡す場合を考える。

test.py内では、

parser.add_argument('--box_path', default = "test")
args = parser.parse_args()
x = args.box  #コマンドライン引数の値を格納
print(x)

としたところ、
 > test 

と出力されていた。

当然で、--boxを誤って--box_pathで指定していただけ。

エラーもはかないから困った。
変数変更でプログラムを変更した際、--boxと変えるのを忘れていた。

parser.add_argument('--box', default = "test")と変更すると、
 > ok

と出力された。

エラーをはかない場合は困ります。。。
GAS初心者がGoogleカレンダーに予定を追加してみた

#はじめに

GASの入門として、Googleカレンダーに予定を追加してみました。
これからGASを始めたいと思っている方の手助けになればと思います。

#ターゲット

- GASを触ってみたい方
- Google APIを触ってみたいが、何から初めて良いか分からない方

#GASとは

Google Apps Scriptの略称。
GmailやGoogle DriveといったGoogle関連サービスと連携するアプリケーション開発のプラットフォーム（公式サイトは[こちら](https://developers.google.com/apps-script)）

#操作手順

主な手順は以下の通りで進めていきます。
　1. GASプロジェクトを作成する
　2. GoogleカレンダーのカレンダーIDを取得する
　3. Googleカレンダーに予定を追加する

##1. GASプロジェクトを作成する

[Google Drive](https://drive.google.com/drive/my-drive)の画面から「＋新規」>「その他」>「Google Apps Script」をクリックする。
![01_GoogleDrive.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/b0648b75-2fbf-7342-e05d-68420f3f3e86.png)

Google Apps Script を開くと、以下のような画面に遷移します。
赤枠の「無題のプロジェクト」となっている箇所をクリックし、任意の名前を設定してください。
※こちらの名称が **プロジェクト名** になります！
![02_GAS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/ab418b8f-de75-1e3a-c27d-a7aed90facf7.png)

##2. GoogleカレンダーのカレンダーIDを取得する

[Googleカレンダー](https://calendar.google.com/calendar/u/0/r)の画面から「マイカレンダー」で指定したいカレンダーを選択する。
オーバーフローメニュー（⋮）をクリックし、「設定と共有」を開く。

![03_カレンダー選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/3567c91a-2cb8-73b4-ec72-93c558ac8931.png)

設定画面にて「カレンダーの統合」をクリックする。
「`xxx@group.calendar.google.com`」形式で記載のあるカレンダーIDを取得する。
![04_カレンダーID.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/83165ae3-ecef-9c38-1489-7a57159591fb.png)
※Googleアカウントのメインカレンダーを選択した場合、カレンダーIDは「`xxx@gmail.com`」形式のメールアドレスがそのままIDになる。

##3. Googleカレンダーに予定を追加する

1.で作成したGASプロジェクトのスクリプトエディタに以下コードを入力する。
プロジェクトを保存し、実行ボタンを押下する。

カレンダー予定追加メソッドについては、別途記事で説明を行う。

```js:コード.gs
function myFunction() {
  const calID = "カレンダーID";
  var date = new Date();
  var calendar = CalendarApp.getCalendarById(calID);
  calendar.createAllDayEvent("〇〇定例会", date);
}
```

上記プロジェクトを実行した日付に、イベント「〇〇定例会」が追加された！
![05_カレンダー追加.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/d21c9e65-303b-0ef8-5c3b-b98dc81e9775.png)

#さいごに
簡単にGASを使用したカレンダーに予定を追加する方法を紹介しました。
今回、紹介しきれなかった予定追加メソッドについては別途記事化したいと思います。

#参考サイト
- [Google Apps ScriptでGoogleカレンダーを操作する最初の一歩のスクリプト](https://tonari-it.com/gas-calendar-first-step/#toc3)
- [GASでGoogleカレンダーに予定を追加する](https://qiita.com/jooji/items/b9d6bd0ed15d187b18d8)
定期的にモデル削除のPrunable機能到着 [Laravel 8.50]


# 概念

定期的に不要になったレコードをDBから物理的に削除したい場合があるとおもいます。今までこの処理をバッチやコマンドで作る必要がありましたがLaravel　8.50のリリースに含んでいる`Prunable`か`MassPrunable`のトレイトをモデルクラスに追加することで、この処理が簡単に実装できます。

# セットアップ

変更履歴のログや調査のため、ユーザーの名前などの情報が変更されるときにＤＢの`UserLog`のテーブルに保存する事を例とします。`UserLog`情報を６ヶ月間保存する必要があり、定期的に６ヶ月間前のレコードをＤＢから物理的に削除します。

# 使い方

## モデルの周り

モデルに`Prunable`のトレイトを追加して、`prunable`の関数に削除対象のレコードをEloquentのクエリビルダで返す機能を実装します。`Prunable`と`MassPrunable`を使うとき論理削除の`SoftDeletes`を利用しているモデルでもクエリに一致した場合、物理的に`forceDelete()`で削除されますので気を付けてください。

```php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;

class UserLog extends Model
{
    use Prunable;

    /**
     * 削除対処のモデルを取得
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function prunable()
    {
        // ６ヶ月前のレコードを取得する
        return static::where('created_at', '<=', now()->subMonths(6));
    }
}
```

もしそのモデルと関連する処理（たとえば、古いプロファイルの写真を削除することや、関連するモデル削除など）が必要な場合、モデルが削除する前に`pruning`という関数で処理が実装できます。

```php

    /**
     * モデルの削除の準備
     *
     * @return void
     */
     protected function pruning()
    {
        //　ここでモデルが削除する前に必要な処理を実装します
    }
```

# スケジュール

`Prunable`を利用しているモデルの削除処理が行われるため、アプリケーションの`App\Console\Kernel`クラスで`model:prune`のArtisanコマンドを登録する必要があります。そのコマンドが実行されると`app/Models`ディレクトリ内にある`Prunable` と`MassPrunable`を利用しているモデルの削除処理が行われます。もしモデルが別のダイレクトリーにあるなら、`--model`のオプションを使って、モデルのクラス名を配列として指定できます。下記の例だと毎日の`03:00`に削除処理が実行されます。

```App\Console\Kernel.php
protected function schedule(Schedule $schedule)
{
    // `app/Models`ディレクトリ内の場合
    $schedule->command('model:prune')
        ->daily()
        ->at('03:00');

    // `app/Models`ディレクトリ以外の場合
    $schedule->command('model:prune', [
        '--model' => [UserLog::class],
    ])->daily()
    ->at('03:00');
}
```

# MassPrunable VS Prunable

`MassPrunable`というのはの複数削除処理が行われ、`Prunable`と違って削除前にレコードを取得せず、複数レコード削除クエリが実行されます。そのため`MassPrunable`の方が`Prunable`より、処理が効率的です。しかし、削除する前にレコードが取得されないため、Eloquentの`deleted・deleting・pruning`のイベントは発火しません。それ以外は、Prunableの実装と同じです。

```php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\MassPrunable;

class UserLog extends Model
{
    use MassPrunable;

    /**
     * 削除対処のモデルを取得
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function prunable()
    {
        // 6ヶ月前のレコードを取得する
        return static::where('created_at', '<=', now()->subMonths(6));
    }
    
    /**
     * モデルの削除の準備
    *
     * @return void
     */
    protected function pruning()
    {
        //　イベントが発生されないので、この関数の処理が行われない
    }
}
```

# 参考

https://github.com/laravel/framework/pull/37696
https://laravel.com/docs/8.x/eloquent#pruning-models
https://laravel.com/api/8.x/Illuminate/Database/Eloquent/Prunable.html
https://laravel.com/api/8.x/Illuminate/Database/Eloquent/MassPrunable.html
Jupyter notebookでボタン起動、出力文字を大きくする、アイコンを入れる

#どんな記事？

* Jupyter notebook出力で、HTML表現を扱ってみた
* ボタンクリックで処理が動くようにしてみた

#動機
Jupyter notebookで書いた処理を、プロトタイプデモ用に見栄えをかっこよくしたかったわけです。
`PySimpleGUI`も立ち上げてみましたが、WSL環境ではディスプレイ出力周りが面倒で、手元環境以外で動かしてもらうのが大変そうに感じました。

ということでJupyter notebook上で完結させたく、

* 出力文字の大きさや太さを変える
* アイコン画像を差し込む
* ボタンで処理起動させる

をやってみました。
特に**HTML表現をすれば良い**と気づくまでに時間が掛かって、あまり情報が落ちてなかったので、記事にしてみました。

#動作環境

* Python 3.6.9
* ipywidgets 7.6.3
* Jupyter Notebook 6.4.0

#参考コード

```code.py
import ipywidgets as widgets
from IPython.display import display, HTML, Image

def visualize(clicked_button: widgets.Button) -> None:
    with output:
        output.clear_output()
        #making output text
        text = 'Correct' if result == 1 else 'Wrong'
        #display
        display(HTML("<big><b>"+text+ "</b></big><br/>,so...<br/>"))
        if result == 1:
            display(Image(filename='いいねの手のアイコン.png', width = 100, height = 100))
        else:
            display(Image(filename='よくないねアイコン1.png', width = 100, height = 100))
           
#for debug
#result = 1    #Correct result
result = 0   #Wrong result

button = widgets.Button(description='Click me')
output = widgets.Output(layout={'border': '2px solid black'})

button.on_click(visualize)
display(button, output)
```

以下のように出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84320/0fa3f555-2ab4-65d7-21b3-47b2e42841ac.png)

#まとめ

* `display(HTML(~~))`で囲めばHTML表現できるので、文字もいじれるし改行もできます
* `display(Image(~~))`で画像が読めます
* ボタン実装は`ipywidgets` でできます


#参考文献

* [jupyter notebookで画像や動画を表示させる簡単な方法](https://self-methods.com/jupyternotebook-ipython-display)
* [ipywidgetsのwidgets色々](https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20List.html)
* [ICOON MONO (本記事で使ったアイコン画像)](https://icooon-mono.com/)
人工知能クラウドコンピューティング


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1826722/8b8a1026-0108-d5b9-ce5d-0aaf628d12ea.png)
Artificial Intelligence cloud computing (Artificial Intelligence), the English abbreviation is AI. It is a new technological cloud solutions science that studies and enterprise cloud services develops theories, methods, technologies and application systems used to simulate cloud computing, extend and managed cloud services expand human intelligence. Artificial intelligence is a branch of computer science. It attempts to understand the essence of intelligence and produce a new intelligent machine that can react in a similar way to human intelligence cloud computing. Research in this field managed cloud services includes robots, language recognition, and image recognition managed cloud services. , Natural language processing managed cloud services and expert systems, etc. Since the birth of cloud solutions artificial intelligence, the theory and technology have enterprise cloud computing become increasingly mature, and the field of application has enterprise cloud services continued to expand. It is enterprise cloud services conceivable that the technological cloud solutions products brought by artificial intelligence in the enterprise cloud computing future will be the "containers" of human cloud solutions wisdom.
【React】遷移先画面へ値を受け渡す

# react-routerの機能を使用する方法
## 遷移先へ値を受け渡す方法
```tsx
import { useHistory } from 'react-router-dom';

const history = useHistory();

history.push({
  pathname: '/foo',
  state: { bar: 'bar' }
});
```

## 遷移元から受け取った値を使用する方法
```tsx
import { useHistory, useParams } from 'react-router-dom';

const location = useLocation<{ bar: string }>();

location.state.bar;
```
Excel のシート名を表示する（ディレクトリ名に "]" がある場合にも対応）

#結論

`=MID(SUBSTITUTE(SUBSTITUTE(CELL("filename",A1),"\",""),"]","\",LEN(CELL("filename",A1))-LEN(SUBSTITUTE(CELL("filename",A1),"]",""))),FIND("\",SUBSTITUTE(SUBSTITUTE(CELL("filename",A1),"\",""),"]","\",LEN(CELL("filename",A1))-LEN(SUBSTITUTE(CELL("filename",A1),"]",""))))+1,31)
`
IBM Cloud Pak for Integration で IBM API Connect を使用してみた ～ クライアント ID とクライアント秘密鍵による API の保護 ～

0. はじめに

[IBM Cloud Pak for Integration で IBM API Connect を使用してみた ～ APIの登録と公開 ～](https://qiita.com/ac_qiita/items/f937015c41ff1350038c) の続きです。

前回は、APIの登録と公開を行いましたが、このままだとAPIのエンドポイントが分かると、誰でもAPIコールできてしまいます。
そこで、ここでは、クライアント ID とクライアント秘密鍵によって API を保護する手順を取り上げます。

本記事でも以下を参考にさせていただきました。
・[クライアント ID とクライアント秘密鍵による API の保護 (IBM Cloud を使用する場合)](https://cloud.ibm.com/docs/apiconnect?topic=apiconnect-tut_secure_id_secret_bm)
・[IBM API Connect 関連メモ - (4)各種APIの管理](https://qiita.com/tomotagwork/items/99e9b35227a0f80b2a91)


2. API保護の設定手順

1) 設定したいAPIの設計画面のページにアクセスし、「セキュリティ」を選択し、「セキュリティー定義を作成するのは、ここをクリックしてください。」をクリックします。
　 ※ここでは、APIの登録と公開の記事で作成した「weather-provider-api」に設定を行います。
![2021-07-26_14h17_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/e506d48a-261c-5c58-d467-27a8231edc97.png)

2) 以下のように入力し、「保存」をクリックします。
名前： Client ID
タイプ： API キー
場所： ヘッダー
鍵タイプ： クライアント ID
パラメーター名： X-IBM-Client-Id
![2021-07-26_14h24_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/b70c9bd0-6580-6c88-ca66-fb00f6a4ceaf.png)

3) 「追加」をクリックします。
![2021-07-26_14h27_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/1f45d66c-6419-8510-372a-617cf07f2b33.png)

4) 以下のように入力し、「保存」をクリックします。
名前： Client Secret
タイプ： API キー
場所： ヘッダー
鍵タイプ： クライアント秘密鍵
パラメーター名： X-IBM-Client-Secret
![2021-07-26_14h29_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/1dfa50e8-3137-e1a6-c4ac-daf2d8a77594.png)
 
5) 「Clinent ID」と「Client Secret」の2つが定義されたことを確認し、「保存」をクリックします。
![2021-07-26_14h31_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/178d09d9-f585-382a-8653-b6b210c46969.png)

6) APIのテストページに行き動作確認を行います。
「X-IBM-Client-Id」「X-IBM-Client-Secret」には自動生成された値が初期設定されています。
「zipcode」に「10504」を入力し、「送信」をクリックします。
![2021-07-26_14h38_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/a1575904-bcbf-bdae-96a1-1ab6ec15ad39.png)

7）結果が返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740352/b0cbca32-4ae5-db4b-daf0-ce7a7a42c1ff.png)
pythonでカレンダーアプリ作成

カレンダーアプリの作成を行いました！

コードは以下の通りになります。


```python:Qiita.py

import tkinter as tk
import calendar as cl
```
tkinterとcalendarをimportし、asを使って省略

```
def pre_month():
    global a
    global b

    if b == 1:
        b = 12
        a = a - 1
    else:
         b = b - 1


  
    lbl.configure(text=cl.month(a,b))
```
関数を追加し、ひと月前を表示させる 
ラベル表示を変更

```
def add_month():
    global a
    global b

    if b == 12:
        b = 1
        a = a + 1
    else:
        b = b + 1
    
    lbl.configure(text=cl.month(a,b))
```
関数を追加し、ひと月先を表示させる 
ラベル表示を変更

```
root = tk.Tk()
root.geometry("300x200")
root.title("カレンダー")
```
画面表示を準備

```
a=2021
b=4
```
変数を作成し、y,mに数字を入れる

```
cv = tk.Canvas(root,width=400,height=300,bg="white")
cv.pack()
```
背景色を追加　今回は白に設定

```
lbl = tk.Label(text=cl.month(a,b))

lbl.pack()
```
カレンダーモジュールを使って文字列型としてカレンダー形式が返ってくる
ラベルとラベルの配置を作成

```
btn1 = tk.Button(text="←",command=pre_month)
btn2 = tk.Button(text="→",command=add_month)

btn1.place(x=100,y=150)
btn2.place(x=150,y=150)
```

ボタンとボタンの配置を作成

```
tk.mainloop()
```
![カレンダーアプリ3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1776372/0dfbaf6b-76f0-28bf-e8f3-1a5bf8281d80.gif)



実行結果　

カレンダーアプリの完成になります。
スピル機能はExcelを快適にできるのか

# はじめに
2019年にOffice365のExcelに実装された、スピル機能。
最近ようやく使い方を覚え、かなり便利に・快適になりました。

関数の記述量が圧倒的に少なくなり、これってかなり軽く・早くなるんじゃないの？
と思い、実査に調べてみようと思い立った次第です。
# 準備
以下の関数をExcelに仕込みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/731969f6-8c47-a56c-d95a-98146262178e.png)
A列 → RAND()
B列 → A列 × RAND()
C列 → A列 × B列
D列 → B列 × C列

これを、オートフィルでExcelの最大1048576行まで指定します。

次に同じ計算をSPILLを使用して再現します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/28998f67-1203-5627-3af9-9aeef4a6f14a.png)
A列 → RAND()　－変わらず
B列 → A列 × RAND()　－A列をスピルで参照
C列 → A列 × B列　－　A列、B列をスピルで参照
D列 → B列 × C列　－　B列、C列をスピル範囲演算子で参照

この2種類のExcelブックを比較します。
# 比較①　ファイル容量

#### スピル無し
→84.3MB
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/a99da807-ec90-6f0d-bf65-ad6a0adad3c1.png)
#### スピル有り
→68.9MB
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/8d4f4855-3ffc-354d-0d9d-cb27b85317ad.png)
# 比較②　ファイルを開く速さ
#### 前提
いずれのファイルも、計算方法の設定を「手動」としています。
手元のiphoneでアナログに計測。

#### 計測結果
|スピル設定|1回目|2回目|3回目|
|-|-|-|-|
|なし|11.74|11.45|11.47|
|あり|9.49|9.77|9.95|
# 比較③　関数の再計算のスピード
#### 準備
以下のように各Excelブックにマクロを仕込んで、自動計算前後の時刻の差分を取得します。

```vb
  Dim startTime As Double
  Dim endTime As Double
  Dim processTime As Double

  '開始時間取得
  startTime = Timer

  '再計算実施
    Calculate

  '終了時間取得
  endTime = Timer
  
   
   '処理時間表示
  processTime = endTime - startTime
  MsgBox "処理時間：" & processTime

```
#### 計測結果
|スピル設定|1回目|2回目|3回目|
|-|-|-|-|
|なし|0.628|0.548|0.617|
|あり|0.562|0.484|0.511|
# まとめ
いずれも、スピルありのほうが良い結果となりましたが、
個人的には、思っていたほどではないかな？という印象でした。

便利な機能であることは間違いないので、積極的に使っていきましょう。
「Yahoo!天気アプリ 雨雲レーダー大幅アップデート開発の取り組み」で学んだこと(デブサミ2021夏)

# はじめに

本稿は、Developers Summit 2021 Summer の以下のセッションで学んだことを書きます。

セッション名：Yahoo!天気アプリ 雨雲レーダー大幅アップデート開発の取り組み
講演者：大前 良介[ヤフー]
セッション詳細：https://event.shoeisha.jp/devsumi/20210730/session/3238/


# 学んだこと

従来の雨雲レーダーは、ユーザーが地図上のデータを読み取って把握する必要があった。
それではユーザーにとって使いづらいため、どの地点にいつどのくらいの雨が降るのか、情報を整理してユーザーに伝えられるようにした。

今回のアップデート前のもともとの雨雲レーダーの時点で、多機能だった。
そしてFatActivityの状態だった。
1つの神クラスで、様々な機能が継ぎ足しで追加されてきた。
一時的にスケジュールを遅延させてでも大規模なリファクタリングを実施した。

完璧を目指すとコストが無限にかかるため、費用対効果を考え、妥協点を設定。
以下の方針で実施。

- 機能ごとにクラスを分割。
- リファクティブプログラミングの導入。
- 雨雲レーダーの半に限定してリファクタリングを実施。

最初の１週間はリファクタリングのみを行った。
その後の開発速度が上がったため、スケジュールへのマイナスインパクトはなかった。

実際に作ってみて、ユーザーにさわってもらわないと、どういう操作が使いやすいか分からない。
最初に操作できるアプリを何人かにさわってみてもらった結果、想定していない操作をすることがあった。
そういう結果を踏まえて、操作方法を改善した。

「Yahoo!天気」と「Yahoo!JAPAN」のAndroid版とiOS版の4つの類似アプリがあるが、それらはそれぞれのOSでの最適なUXを提供するために、あえて仕様やコードを共通化していない。
ただし、お互いにフィードバックし合うことで、良い点を共有しあっている。

以下の2種類のフィードバックを活用した。
たくさんの改善案が提案された。特にバグバッシュは1つの指摘をきっかけに次々に改善点が見つかった。

- Slackでのフィードバック募集
- Zoomで集中バグバッシュ


# まとめ
有名なYahoo!天気アプリが、開発現場でどのように考えられて開発されているのかが分かり、勉強になりました。

ちなみに私は、普段はエンジニアリングマネージャーとして、チームの皆で楽しく開発する施策を色々実施しています。詳しくは以下を参照ください。
[1年以上かけて生産性倍増＋成長し続けるチームになった施策を全部公開](https://qiita.com/kojimadev/items/4b28f801863cf4e8f0da)

Twitterでも開発に役立つ情報を発信しています → [@kojimadev](https://twitter.com/kojimadev)
API BlueprintでAPI仕様書を書いてみる　導入編


チームでAPI仕様書の書き方を統一しようということになって、API Blueprintを使ったらとても便利でした。

### 良い点

- マークダウンが使える
- わかりやすい
- 見た目がかっこいい！

# やること

API Blueprintは拡張子が.apibなのでhtmlに変換するためにaglioをインストールします。
インストールするにはnpmが必要なのでnpmをインストールします。
### Node.js/npmをインストールする

- mac版
https://qiita.com/mk185/items/7ad004bf202f400daea1
（LTS：長期の保守運用向けバージョン/CURRENT:最新版だけど安定性は保証していないことで機能追加を盛り込んだバージョン）

- windows版
https://qiita.com/taiponrock/items/9001ae194571feb63a5e


### aglioをインストールする
```
$npm install -g aglio
```
### apibファイルを作成
https://apiblueprint.org/documentation/examples/real-world-api.html
Real World APIをエディタにコピペして拡張子.abibで保存

### ローカルで確認
```
$aglio -i <コピペした保存したファイル名.apib> --s
```

ブラウザで以下アクセスする保存したサンプルAPIファイルが表示される
http://localhost:3000/

### HTMLファイルに生成する場合
```
aglio -i <コピペした保存したファイル名.apib> -o <HTMLに変換したいファイル名>.html
```

# できあがり

新規でapibファイルを作成
![1627865134.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/685449/71085efc-1196-ac73-91cc-56ed1192aa07.png)



apibファイルの中身はこれー↓↓

```
# Group サンプルページ


## 会社情報 [/api/company/{cityId}/]

### 会社情報取得API [GET]

#### 処理概要

* サンプル会社情報取得

+ Parameters

    + cityId: 27210 (number, required) - 市区町村ID

+ Response 200 (application/json)

    + Attributes
        + data (required)
            + areaData (required)
                + cityId: 27210 (number)  - 市区町村ID
                + cityName: 枚方市 (string)  - 市区町村名
            + clientData (required)
                + image: /images/sample.jpg (string, required)  - ロゴ画像
                + name: サンプル株式会社 (string, required)  - 会社名
            + image
                + exterior  (array[object], fixed-type)
                    + (object)
                        + image:  /images/sample1.jpg (string)  - 画像ファイルパス
                        + caption: サンプル画像  (string)  - 画像説明文
```


git管理してメンバーで共有しております。

書き方について詳しくは次回！！！

VS CODEを使ってる人は「API Elements extension」の拡張機能を使うと便利です。
[Rails]Bootstrapでヘッダーを整える

今回は、Bootstrapを使ってヘッダーにハンバーガーメニューの導入を行っていきます。

ヘッダーを指定した画面幅に応じて、コンテンツを表示したり、三本線の画像（ハンバーガーメニュー）を表示したりを切り替えていきます。

#開発環境

> ruby 2.6.3
> Rails 5.2.6
> Bootstrap 4.5

#前提

前提として、Bootstrapの導入が行われている状態で説明していきます。

#いきなり完成形

まずは、こんなことをして〜、の前にいきなり完成形のコードをのせておきます。


```erb:header
    <header class="sticky-top">
      <nav class="navbar navbar-expand-md navbar-dark bg-dark text-white">
        <a>
          <%= link_to 'Top', root_path, data: {"turbolinks" => false} %>
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNavDropdown">
          <ul class="navbar-nav ml-auto">
            <% if user_signed_in? %>
              <li class="nav-item">
                <%= link_to '投稿フォーム', new_post_path %>
              </li>
              <li class="nav-item">
                <%= link_to '投稿一覧', posts_path %>
              </li>
              <li class="nav-item">
                <%= link_to 'ランキング', ranks_rank_path %>
              </li>
              <li class="nav-item">
                <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
              </li>
            <% else %>
              <li class="nav-item">
                <%= link_to "新規登録", new_user_registration_path %>
              </li>
              <li class="nav-item">
                <%= link_to "ログイン", new_user_session_path %>
              </li>
            <% end %>
          </ul>
        </div>
      </nav>
    </header>
```

これだけで、あとはよろしく〜では、雑すぎるので、解説していきます。

#ヘッダーを固定

```erb:header
    <header class="sticky-top">
:
```

まず、ヘッダーを画面上部に固定します。
classにsticky-topをつけるだけで、上部に固定できます。（Bootstrap優秀〜）

#ブレークポイントの指定

```erb:header
 <!--ブレークポイントの指定-->
 <nav class="navbar navbar-expand-md">
:
```

わかりにくいので、背景色、色の指定等の記述は削除しています。

`navbar-expand-md`で、mdでナビゲーションバーとハンバーガーメニューの切り替えを行います。

#ハンバーガーメニュー部分

ハンバーガーメニューアイコンの設置と開いたり閉じたりの処理を行っています。

```erb:header
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
  <span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
:
```

`#navbarNavDropdown`を対象に開閉を行っていきます。

「navbar-toggler」classが付与される要素にdata-toggle="collapse"、data-target="#[id名]"、aria-controls="[id名]"、aria-expanded="false"、aria-label="Toggle navigation"

#まとめ

ハンバーガーメニューの実装がかんたんに実装できました。

[Bootstrap日本語リファレンス](https://getbootstrap.jp/docs/4.5/getting-started/introduction/)にも説明がありますので、ぜひ調べてみてください。
Pythonのwindllでメッセージボックスを使いこなす

今回はPythonのwindllを使ってメッセージボックスを表示させます。
tkinterやwxPythonを使わない方法です。
まぁtkinterやwxPythonを使った方が簡単なので、今回の記事はあんまり需要はないと思いますが...

tkinterやwx向け↓
<a href="https://programming-self-study.blogspot.com/2021/07/wxpython.html">wxPythonでメッセージボックスを表示させる</a>
<a href="https://programming-self-study.blogspot.com/2021/07/tkinter.html">Tkinterでメッセージボックスを表示させる -メッセージボックスをフルに使う-</a>

<font color="red">っで、windllなのでWindowsじゃないと実行できません！</font>

Macとかではエラーになると思うので。

#サンプルコード

```Python
import sys
from ctypes import *

user32 = windll.user32

user32.MessageBoxW(0, "This is MessageBox\nOK ボタンと「i」アイコン","Title", 0x00000000|0x00000040)
user32.MessageBoxW(0, "This is MessageBox\nOK キャンセル ボタンと「?」アイコン","Title", 0x00000001|0x00000020)
user32.MessageBoxW(0, "This is MessageBox\nはい いいえ ボタンと「?」アイコン","Title", 0x00000004|0x00000020)
user32.MessageBoxW(0, "This is MessageBox\nはい いいえ キャンセル ボタンと「!」アイコン","Title", 0x00000003|0x00000030)
user32.MessageBoxW(0, "This is MessageBox\n中止 再試行 中止 ボタンとエラーアイコン","Title",0x00000002|0x00000010)
user32.MessageBoxW(0, "This is MessageBox\n再試行 キャンセル ボタンと「!」アイコン","Title", 0x00000005|0x00000030)
user32.MessageBoxW(0, "This is MessageBox\nキャンセル 再実行 続行 ボタンとエラーアイコン","Title",0x00000006|0x00000010)
a=user32.MessageBoxW(0, "戻り値もあります。","Title",0x00000003|0x00000030)
user32.MessageBoxW(0,"戻り値：" + str(a),"タイトル",0x00000040)

#戻り値
#はい: 6
#いいえ: 7
#キャンセル: 2
#OK: 1
#再試行: 4
#中止: 3
#再実行: 10
#続行: 11
#無視: 5
```
環境はWindows 10 Pro ですが場合によっては正しく表示されない場合があります。
そのときはMessageBoxAを使いましょう。

![msgw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1061021/6db8b970-f66b-17ae-9518-75a0e18909a6.png)


##アイコンの指定
|コード |内容 |
|---|---|
|0x00000010 |エラーアイコン |
|0x00000020 | はてなアイコン |
|0x00000030 |警告アイコン |
|0x00000040 |情報アイコン |

##ボタンの指定

|コード |内容 |
|---|---|
|0x00000000 | [OK]
|0x00000001 | [OK] [キャンセル]
|0x00000002 | [中止] [再試行] [無視]
|0x00000003 | [はい] [いいえ] [キャンセル]
|0x00000004 | [はい] [いいえ]
|0x00000005 | [再試行] [キャンセル]
|0x00000006 | [キャンセル] [再実行] [続行]

##デフォルトボタンの指定

|コード |内容 |
|---|---|
|0x00000000 |最初のボタン |
|0x00000100 |二番目のボタン |
|0x00000200 |三番目のボタン |

##その他オプション

|コード |内容 |
|---|---|
|0x00040000 |常に最前面 |

##戻り値

|コード |内容 |
|---|---|
|1 | [OK]|
|2 | [キャンセル]|
|3 | [中止]|
|4 | [再試行]|
|5 | [無視]|
|6 | [はい]|
|7 |  [いいえ]|
|10 | [再実行]|
|11 | [続行]|

---

まぁこのメッセージボックスを使う意味はあまりないと思いますが、windllで独自GUIライブラリを作りたいって人は必要になるかもしれません。
【Python】forrtl: error (200): program aborting due to control-C eventと表示されたときの対処法



## 症状

anacondaでpythonの仮想環境を作って動かしたプログラムをCtrl+Cで強制終了しようとしたら以下のエラーがでた。動作環境はWindows10 Python3.8.5

```
forrtl: error (200): program aborting due to control-C event
Image              PC                Routine            Line        Source
libifcoremd.dll    00007FFF0F3A3B58  Unknown               Unknown  Unknown
KERNELBASE.dll     00007FFF857E4573  Unknown               Unknown  Unknown
KERNEL32.DLL       00007FFF88C67974  Unknown               Unknown  Unknown
ntdll.dll          00007FFF891EA2F1  Unknown               Unknown  Unknown
```



## 対処法

使ってたライブラリ（scipy）が古かったらしい。

```
pip install --upgrade scipy
```

アップグレードしたら治った。それだけ。



## 参考元

https://living-sun.com/ja/python/687992-ctrl-c-causes-forrtl-error-200-rather-than-python-keyboardinterrupt-exception-python-keyboardinterrupt.html