OmniAICreator/Qiita-1.07M huggingface dataset:
Nest.js × gRPCでts-protoを使っている場合は注意!

サーバー間通信でgRPCを採用しているProductも増えてる中で、BFFとbackendサービスを分けてマイクロサービス化を進めてる最近ですが。
直近２日程ハマった事象があり、同じ事象に遭遇した人の助けになればと思い書かせて頂きます。


## 環境
- 仕様言語: TypeScript
- Framework: nest.js v7.x
- 実行環境: docker（node:16）

## 発生した事象
普段はMacで開発しているのですが、諸事象によりWindows環境で開発をここ数日している中で発生しました。
ただし開発はrepositoryにコミットしてあるdocker内で開発するので特に問題はないはずでした。
開発の流れは以下に流れになります。

```
1. dockerで開発環境を作成（この時にgrpc関連と開発に必要なパッケージはインストールされます）
2. protoファイルに修正がある場合は修正を行う
3. ts-protoでprotoファイルからtsファイルを自動生成する  
```

上記の3まで完了しgitの差分を確認した時に不思議な事が発生しました。

```
-import { Metadata } from "grpc";
+import { Metadata } from "@grpc/grpc-js";
```

意図しない差分が発生していて、調査をしてみると `@grpc/grpc-js` は **nest.js v8.x** からの対応となっていました。
本番稼働しているシステムのフレームワークのメジャーバーションを上げるわけにもいかず、どうにか **grpcパッケージ** を指定できないか調査をしていた時に、一週間前にmacで同じ手順の作業をした時は問題がなかった事を思い出しました。

**ts-protoで何か変更が直近発生した??**
→ ありました原因が。（しかも一週間以内にリリースされていた...）
https://github.com/stephenh/ts-proto/releases/tag/v1.83.1

```
Bug Fixes
deprecated grpc and replace with @grpc/grpc-js (#362) (1a11b97)
```

## 対応作業

- packageのversionを固定して再インストールを実施

※npmの場合は適時読み替えて下さい

```
yarn global remove ts-proto
yarn global add ts-proto@1.83.0
```

- 再度protoからtsファイルを作成 → 差分なし

## 結論
nest.js v7.x系もしくは以下を使用していて、ts-protoでprotoファイルからtsファイルを作成している場合は、ts-protoのversionを **v1.83.0** までで固定した方が良さそうです。
nest.js v8.x系の場合は、`@grpc/grpc-js` を [サポート](https://github.com/nestjs/nest/pull/4806) しているので特に問題はなさそうですが。
それでも、ts-protoのversionは固定しておいた方が良さそうです。
特にdocker環境でチームメンバーに配布するなら特に良いかなと思いまいた。

※ grpcパッケージはdeprecatedステータスで **@grpc/grpc-js** への乗り換えが推奨されているので特別な理由がない限り乗り換えた方が良さそうです。
https://www.npmjs.com/package/grpc
Android x86のlive USBでデータを保持する

Android x86ではUSBからの起動ができますが、そのままでは一度電源を切るとデータが消えてしまいます。
あまり煩雑でない手順でデータの保持ができたので、以下にその方法をまとめます。
(Windows向けの手順です。Linuxの場合はWSLをターミナルに置き換えれば大丈夫かと思います)

#手順
1. Android x86のISOをダウンロードし、Rufus等のソフトを利用してUSBメモリに書き込む。
1. WSL2でUSBメモリをマウントし、ドライブ直下にデータ保存用の領域をimgファイルとして作成する。(countの数値は領域のサイズ(MB)です。)
      
    ```
    dd if=/dev/zero of=data.img bs=1M count=2048
    ```

1. 作成した領域をext4でフォーマットする。

    ```
    mkfs.ext4 data.img
    ```

以上の手順で、USBから起動したAndroid x86でもデータが保持されるようになりました。

#参考ページ

https://www.youtube.com/watch?v=HqicHGxK2PA

https://arekorebibouroku.hateblo.jp/entry/2016/10/10/233704
Strategy Pattern (移譲) の採用可否基準と実装例


|関連記事のトップページ|
|:--|
|[[シリーズ] Python におけるデザインパターンの記録](https://qiita.com/robozushi10/items/3c1c0d1b1fbf7b38a33b)|

## 概要

移譲構造 (Strategy Pattern ≒ C言語の関数ポインタ) の「採用可否の基準」と「実装例」.
引用元は下記書籍である.

ただし、内容について細かく記すと書籍の無断転載になるので大まかに記している.
また、コードは Ruby から Python に書き換えている.

|引用元情報|一言|
|:--|:--|
|[書籍 -- Rubyによるデザインパターン (Russ Olsen 著)](https://www.amazon.co.jp/Ruby%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-Russ-Olsen/dp/4894712857)|[原書(英文)](https://www.amazon.com/gp/product/0321490452/ref=as_li_ss_tl?ie=UTF8&tag=eloqruby-20&linkCode=as2&camp=217145&creative=399349&creativeASIN=0321490452)|
|[GitHub -- 著者 Russ Olsen 氏](https://github.com/russolsen/design_patterns_in_ruby_code/tree/master/01)||


## 採用の基準

ここは独断もしくは私の解釈です.

採用基準は次を満すこと.
・**基底クラスの仕様に変更が生じる確率ありそうなので "継承" はしたくないが、シーケンス実装は継承させたい**

言い換えると次である.
・**継承せずに関数ポインタを実現したい**



## コード例

### ファイル構成

```bash
.
|-- ex3_vehicle.py
|-- ex5_engine.py
|-- ex6_car_delegation.py
`-- ex6_car_delegation_test.py

```

### クラス図

Vehicle を基底クラスとして採用とし、
全ての乗り物で必ず存在する 重量(weight) のみを保持させる.

他方、乗り物によっては存在しないエンジンは Vehicle から切り離して、
Engine クラスとして別途作成する.

そして、具象クラスの Car から Engine を参照(≒ポインタ)する.

・重量 (weight)
・エンジン稼働 (start_engine)
・エンジン停止 (stop_engine)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/ccde34c3-e7bd-042f-4da1-2ef0f3dfcd04.png)






### ./ex3_vehicle.py

「乗り物」を表わす基底クラス Vehicle.

全ての具象クラスで "共通" かつ "仕様変更が発生しない" 情報のみを保持させる.

```python
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys; sys.dont_write_bytecode = True

class Vehicle(object):
  def __init__(self, weight):
    self.weight = weight   #! 重さ
    print(f'This car weighs {self.weight}kg')

```

### ./ex5_engine.py

エンジン

```python
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys; sys.dont_write_bytecode = True

class Engine:
  def start(self):
    print('start the engine')

  def stop(self):
    print('stop the engine')

```

### ./ex6_car_delegation.py

具象クラス

```python
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys; sys.dont_write_bytecode = True
from ex3_vehicle import *
from ex5_engine import *

class Car(Vehicle):
  def __init__(self, weight):
    super().__init__(weight)
    self.engine = Engine()

  def start_engine(self):  #! エンジン稼働
    print('start the engine')

  def stop_engine(self):   #! エンジン停止
    print('stop the engine')

  def sunday_drive(self):
    self.engine.start()
    print('cruise out into the country and return')
    self.engine.stop()

```

### ./ex6_car_delegation_test.py

テストドライバ

```python
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import sys; sys.dont_write_bytecode = True
import unittest
from ex6_car_delegation import *

class CarWithDelegationTest(unittest.TestCase):
  def test_car(self):
    c = Car(weight=650)
    c.sunday_drive()

```


## 実行例

```bash
$ python -m unittest ex6_car_delegation_test.py
This car weighs 650kg
start the engine
cruise out into the country and return
stop the engine
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
```

以上.
webp画像対応でレスポンスの軽量化

### はじめに
Webサイトではたくさん画像を使うケースが多いです。
数MBの画像を多いと反応が遅くなってしまい、利用者がストレスになりやすいです。

### レスポンスを早くする案
#### 案1. 事前にデバイスごとでリサイズ
よく想定できる案ではありますが、PC用、Tablet用、スマホ用の画像を用意し、UserAgentを基づいて出しわけをし、
レスポンスを早くなるわけです。

デメリット：
・画像アップロード時に加工する必要があるため、開発・テスト工数増
・フロント側も出しわける処理が必要のため、開発・テスト工数増
・実ファイルは増えるため、Storage量増（料金増）

#### 案2. アクセスする際にデバイスごとでリサイズ
画像アップロード時はリサイズせずに、フロント側からアクセスする際に指定したリサイズを返す

例えばAlibaba OSS、AWS Lambda@Edgeなどのサービスを利用。

#### 案3. 容量が小さい画像形式に統一
同じく、画像アップロード時は加工する必要がありますが、フロント側の出し分け処理は不要です。

Webpはこの有力な選択肢ではあります。

##### Webpとは
>WebP is a modern image format that provides superior lossless and lossy compression for images on the web. Using WebP, webmasters and web developers can create smaller, richer images that make the web faster.
>
>WebP lossless images are 26% smaller in size compared to PNGs. WebP lossy images are 25-34% smaller than comparable JPEG images at equivalent SSIM quality index.

出典：https://developers.google.com/speed/webp

元ファイルの30%程度に小さくなります。

##### 変換ツール
https://developers.google.com/speed/webp/docs/precompiled

##### JAVAの変換ライブラリ
https://github.com/sejda-pdf/webp-imageio

JAVAでコマンドを呼んで変換してもよいが、ライブラリを使ったらミドルウェア依存しなくなります。

##### Node.js: webp-converter
https://www.npmjs.com/package/webp-converter

以上
.prefix()で指定した文字数目までの文字列を取得する

#今回の内容

* `.prefix()`で指定した文字数目までの文字列を取得する

#コードと簡単解説

```Swift:
    let string01 = "abcd"
    let string02 = "1234"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        print(string01.prefix(1))
        print(string01.prefix(3))
        print(string02.prefix(1))
        print(string02.prefix(2))
}
```

```:print結果
a
abc
1
12
```
# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
【Rails】マイグレーションでDATE型のデフォルトを現在日時にする

レコードが作成された日時をデフォルトにカラムが作成されるようにしたい。
DATETIME型で現在日時をデフォルトに入力する方法は多々見つかったものの、DATE型については情報があまり見つからなかったのでメモする。

# DATE型で現在の日時をデフォルトにする
#### migration
```
t.date :date, null: false, default: -> { '(CURRENT_DATE)' }
```
※`()`を忘れずに!!

#### 確認
```
mysql> show columns from テーブル名 like "date";
+---------+------+------+-----+------------------+-------------------+
| Field   | Type | Null | Key | Default          | Extra             |
+---------+------+------+-----+------------------+-------------------+
| date    | date | NO   |     | (curdate())      | DEFAULT_GENERATED |
+---------+------+------+-----+------------------+-------------------+
```

<br>

## おまけ
### 現在から5日後をデフォルトにする
##### migration

```
t.date :date, default: -> { '(CURRENT_DATE + INTERVAL 5 DAY)' }
```

##### 確認

```
mysql> show columns from テーブル名 like "date";
+---------+------+------+-----+------------------------------+-------------------+
| Field   | Type | Null | Key | Default                      | Extra             |
+---------+------+------+-----+------------------------------+-------------------+
| date    | date | NO   |     | (curdate() + interval 5 day) | DEFAULT_GENERATED |
+---------+------+------+-----+------------------------------+-------------------+
```

<br>

### NG記法
```
t.date :date, default: Time.now.to_date
```
レコード作成時ではなく、`Time.now.to_date`= テーブル作成時の日付をデフォルトに設定されてしまう。

<br>

### DATETIME型で現在時刻をデフォルトにする
```
t.datetime :update_date, default: -> { 'NOW()' }
```

<br>

## 環境
- Rails 6.1.4
- mysql:8.0
Flutter for Webの初期化時に読込中表示を出す方法

![Timeline-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44103/13d3c9a2-c7d0-0fc6-385a-86a93c65872b.gif)

Flutter 2.5.1現在、Fluuter for Webのデバッグ時には上のgifのような読込中のインジケータ（ローディング画面）が表示されますが、現時点では**デバッグ時のみ**でリリースビルド時には表示されず、表示させるオプションは見当たりません。

リリースビルド後、現時点で初期読み込み時間が10秒程度かかってしまうことはよくあることなので、**リリース時にもデバッグ時と同じ読込中表示を出す方法**をご紹介します。

（根本的な問題である、`main.dart.js`のサイズが大きい問題や、マテリアルアイコンのフォントサイズが大きい問題には今回は触れません。(参考: [main.dart.js is too large #46589](https://github.com/flutter/flutter/issues/46589)) ）

## 方針

読込中インジケータにはいろんな種類がありますが、今回は実際にデバッグ時に使われているものをそのまま表示させたいので、`packages/flutter_tools/lib/src/web/bootstrap.dart` に記載のコードを極力コピーして再利用します。

https://github.com/flutter/flutter/blob/master/packages/flutter_tools/lib/src/web/bootstrap.dart

実装としては、windowのloadイベントのタイミングでインジケータを消す方法がindex.htmlをいじるだけなので簡単ですが、それだと実際にFlutterのUIが表示されるまで案外ラグが大きいので、今回はFlutterのmain関数が呼ばれるタイミングで消えるようにしました。

## index.html

まず、`web/index.html`の`<body>`内に次を書き加えます。（styleとscriptは`<head>`内でも構いません。）

```html:index.html
<style type="text/css">
.flutter-loader {
    width: 100%;
    height: 8px;
    background-color: #13B9FD;
    position: absolute;
    top: 0px;
    left: 0px;
}
.indeterminate {
    position: relative;
    width: 100%;
    height: 100%;
}
.indeterminate:before {
    content: '';
    position: absolute;
    height: 100%;
    background-color: #0175C2;
    animation: indeterminate_first 2.0s infinite ease-out;
}
.indeterminate:after {
    content: '';
    position: absolute;
    height: 100%;
    background-color: #02569B;
    animation: indeterminate_second 2.0s infinite ease-in;
}
@keyframes indeterminate_first {
    0% {
        left: -100%;
        width: 100%;
    }
    100% {
        left: 100%;
        width: 10%;
    }
}
@keyframes indeterminate_second {
    0% {
        left: -150%;
        width: 100%;
    }
    100% {
        left: 100%;
        width: 10%;
    }
}
</style>

<script>
function flutterReady(){
    // console.log("flutter app is ready");
    var el = document.getElementsByClassName('loading')[0];
    if(el){ el.remove(); }
};
</script>

<div class="flutter-loader"><div class="indeterminate"></div></div>
```

## main.dart

次に、`main.dart`に以下の記載を加えます。

```dart:main.dart
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:js/js_util.dart' as js_util;
import 'dart:html' as html;

void main(){
  if (kIsWeb) {
    if (js_util.hasProperty(html.window, "flutterReady")) {
      js_util.callMethod(html.window, "flutterReady", []);
    }
  }

  // runApp(App()); などメインの処理
}
```

これで完成です。あとは実際にリリースビルドすれば、初回ロード時だけインジケータが表示されると思います。（もし`build`以下のindex.htmlが書き換わっていない場合は`web`以下からコピーすればOKです。）

一度この雛形を組んでしまえば、index.htmlを好きにいじることで自分の好きなローディング画面を出すこともできるので、何かと便利だと思います。
WireSharkの使い方 メモ

ネットワークを監視する。便利。たまにつかう:relaxed:

#WireShark とは
ネットワークプロトコルアナライザ。
コンピュータがネットワークを介して通信するパケットを収集し、その内容や送信先などを解析することができる。
TCP/IP通信の場合、自分宛のIP アドレスでかつ指定したポートのみデータを受信する。しかし、
WireSharkはボードに届くすべてのパケットをモニタすることができる

#WireShark の利点
ネットワーク上に流れているパケットを監視することで、不正アクセスやネットワーク上の問題解析等に利用できる。
ただし、Wireshark は自身のインターフェースに届いたパケットを解析するだけなので、
他のインターフェースに対するパケットを監視したい場合はリピータハブやミラーリング機能のあるスイッチングハブを利用する必要がある。

#ウィンドウ内の表示メモ
|リストのフィールド名||
|:-----------|:-----------|
|Source|パケットを送信した送信元機器のアドレス（MAC アドレスまたは IP アドレス）|
|Destination|パケットの宛先となる送信先機器のアドレス（MAC アドレスまたは IP アドレス）|
|Protocol|解析して判明したパケットのプロトコル|
|Length|パケットのデータの長さ|
|Info|パケットを解析して判明した、通信内容（Wireshark 側でわかりやすく表現している）|

|選択したパケットの表記||
|:-----------|:-----------|
|Frame|データリンク層のパケットの区切り|
|EthernetⅡ|データリンク層のデータ。通信相手は、同一セグメント内に限られる|
|InternetProtocol|インターネット層のデータ。IP アドレスなどで、端末の通信時に用いられる|
|User Datagram|トランスポート層のデータ|
|HypertextTransferProtocol|アプリケーション層のデータ。項目名はプロトコルにより変化する|

##見るときのポイントメモ
* 送信元 MAC アドレスと宛先 MAC アドレスはどうなっているか。
* 送信元 IP アドレスと宛先 IP アドレスはどうなっているか。
* 送信元ポート番号と宛先ポート番号はどうなっているか。
* 送信データの中身はどうなっているか。
Windows2022 Serverを使ってADを構築しました

Windows2022 Server Standard Edition評価版を使ってADを構築しました。
ドメインコントローラー(DC)を仮想化ソフトウェアVirtual Boxを使って2台構築しました。

構築手順
①あらかじめPowershellを作って（ADの機能を構築)
②Powershellを使ってプライマリーDCをインストール
③Powershellを使ってセカンダリーDCをインストール

以上でADとDCを構築します。

Powershellはコマンドベースで簡単に作っています。
エンジニアを目指した話

# はじめに

この記事は、Qiitaの10周年を記念したキャンペーンの一環として開催されている「10年前の自分に伝えたい、勉強しておきたかった技術」をテーマとした記事投稿イベントです。

https://qiita.com/official-events/1e99fc384200c38548fd

まず簡単に私の自己紹介をしたいと思います。
私は大学で情報系の学科を卒業後、製造業のソフトウェアエンジニアとして就職しました。現在、二年目のエンジニアとして働いています。

さて本題に入りますが、私は今24歳ですので、10年前は14歳ということになります。中学2、3年？ですね。正直、私が中学生の時はエンジニアのための勉強は全くしておらず、普通に学校の中間テストや期末テストに向けて勉強していた状態です。ただ、その時に触れていた技術によって、「大学では情報系を学びたい」や、「エンジニアを目指そう」と思うきっかけになったので、その話をしようと思ってこの記事を書きました。よろしくお願いいたします。

# 結論：インターネット
セクションのタイトルとして書きましたが、結論として、私が中学生の時に「大学では情報系を学びたい」や、「エンジニアを目指そう」と思うきっかけになった触れていた技術というのは、**「インターネット」**のことです。
当時、私は携帯（ガラケーやスマホ）やパソコンは持っていなくて、インターネット、ましてやコンピュータサイエンスとは遠い存在でした。ただ、一つだけインターネットにつながるデバイスとして、PSP（プレーステーション・ポータブル）を持っていました。私がPSPで遊んだものの中でプレイ時間2500時間もやり続けた（廃人）ゲームがありました。それは、ファンタシースターポータブル2 インフィニティというゲームです。

https://phantasystar.sega.jp/psp2i/

公式サイトを見ると、とても懐かしさを感じます。2015年の9月にサービスも終了していて、悲しいですね...。ところでなぜこのゲームにそこまでの時間を費やしたのか？疑問に思うはずです。ゲームの内容が面白かったというのも理由ではありますが、もっと私自身、衝撃的な理由があります。それはインターネットマルチモードです。インターネットに接続して、日本中の知らない人たちと遊ぶことができます。今では当たり前の話ですが、当時の私は感激していました。というのも、私は一人っ子でとても寂しがり屋の子供でした。スマホ等を持っていなかったので、学校が終わって、友達と遊び終わったあと、家で一人でいることが多く、とても寂しい気持ちになっていたことを覚えています。その中で、インターネットマルチモードにより、いろんな人たちとゲームをしたり、会話をしたりをすることが非常に楽しく、自分の寂しい気持ちを和らぐことができました。ゲームの中で会話することがかなり多く、Lineで友達と話す感覚でこのゲームを使っていたので、こんなにプレイ時間が多くなってしまいました。私はこのゲームによって、**「インターネットってすごい！」**って思うようになりました。それと同時に、インターネットをもっと知りたい、詳しくなりたいと思うようにもなりました。これがきっかけとなり、大学では、情報系を学び、それからエンジニアになりました。

# まとめ
今の時代、インターネットは身近にあります。

Qiitaの10周年を記念したキャンペーンの一環として開催されている記事投稿イベントでもう一つの「10年後のために今勉強しておきたい技術」をテーマとして記事も書きましたが、クラウド技術は非常に重要な技術ですし、根底にあるインターネット、ネットワークは欠かせないものです。

https://qiita.com/official-events/12fc7bacec894d33a981

https://qiita.com/michimichix521/items/c0cb92a34002b977882d

10年前の自分に伝えたいこととして、よくインターネットに前向きに向き合ってくれた！と言ってあげたいです。そして、勉強しておきたかった技術として、インターネット、さらにはネットワークを学ぶといいねということも言いたいですね。

ここまで読んでいただき、ありがとうございました！
Cargo.tomlの「bar = { package = "foo" }」ってなんだ

## `package` キーを使うとクレートに別名を付けられる
Rustの勉強がてら、クラメソさんの「[RustをつかってAWS Lambdaを実装＆AWS CDKでデプロイする](https://dev.classmethod.jp/articles/rust-lambda-cdk/)」を読んでいたところ、Cargo.tomlの `[dependencies]` に以下のような記述がされていました。

```Cargo.toml
[dependencies]
lambda = { package = "netlify_lambda", version = "0.2.0" }
```

この `package` という記述を見たことがなかったので調べたところ、どうやらこれでプロジェクト内で使うクレート名を変更できるようです。
左辺に使いたい別名、`package` の方に本来のクレート名を書きます。

上記の例では `netlify_lambda` が本来のクレート名([netlify_lambda](https://docs.rs/netlify_lambda/0.2.0/netlify_lambda/))で、 `lambda` が自分でつけた別名ということですね。

なのでこの場合、例えば `netlify_lambda` クレートの `run` 関数は、 `netlify_lambda::run` ではなく `lambda::run` のように記述します。

なおこの方法で別名を付けた場合、元の `netlify_lambda` という名前ではアクセスできなくなります。
局所的に別名にしたいだけなら、import時に `use foo as foo_alias` とした方がよさそうですね。
 
以上。

参考
[Renaming dependencies in Cargo.toml](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#renaming-dependencies-in-cargotoml)
upper_bound (paizaランク B 相当)　学習記録（自分用）

# はじめに
Paizaの問題集を解いた際のメモ。
一応クリアはしたものの良い実装ではないと思うのであまり参考にはならないかと思います。
あくまでも自分用の学習メモ。

問題集＞二部探索メニュー＞upper_bound
問題URL：https://paiza.jp/works/mondai/binary_search/binary_search__basic_step2

# 問題
> n 人の生徒が受けた、10^9 点満点のテストの採点結果 A_1, A_2, ..., A_n があります。あなたは合格点を自由に設定することができます。合格点が k 点のとき、k 点より大きい点数を取った生徒が合格で、k 点以下の点数を取った生徒が不合格です。

### 入力値
> n
A_1 A_2 ... A_n
q
k_1
k_2
...
k_q

> 1行目に、生徒の人数 n が与えられます。
2行目に、採点結果 A_i が半角スペース区切りで与えられます。
3行目に、合格点の候補数 q が与えられます。
続く q 行のうち i (1 ≦ i ≦ q) 行目に、合格点の候補 k_i が与えられます。
q 個の整数 k_1, k_2, ..., k_q が与えられます。各 k_i について、合格点が k_i のときに合格する生徒の数を答えてください。

### 条件（ここがポイント）
> ・ 入力はすべて整数
・ 1 ≦ n ≦ 100,000
・ 0 ≦ A_i ≦ 10^9 (1 ≦ i ≦ n)
・ 1 ≦ q ≦ 100,000
・ 0 ≦ k_i ≦ 10^9 (1 ≦ i ≦ q)

データ数が多いため線形探索では、処理時間がオーバーしてしまうためアルゴリズムをうまく活用する必要あり。


# 実装
二分探索法を用いて実装した

```php
<?php
    $student_number = trim(fgets(STDIN));
    $student_score_array = explode(' ', trim(fgets(STDIN)));

    //二部探索法を用いるためにはそーつする必要がある
    sort($student_score_array);
    
    $q = trim(fgets(STDIN)); //合格点候補の数
    
    //二分探索法でざっくりと合格基準点あたりの生徒番号（key）を求める
    for ($i = 0; $i < $q; $i++) {
        $reference_score = trim(fgets(STDIN));  //合格点
        $left = 0;
        $right = $student_number-1;
        $flag = false;
        
        //二分探索である程度絞る
        while ($left <= $right) {
            $mid = floor(($left+$right) / 2);
            if ($student_score_array[$mid] == $reference_score) {
                break;
            } elseif ($student_score_array[$mid] < $reference_score) {
                $left = $mid + 1;
            } else {
                $right = $mid - 1;
            }
        }
        //ここでの$midは、基準点あるいは基準点に近い値だった生徒の番号が格納されている
        
        //２分探索法で求めた値が、実際に基準点より点数が高いかどうかを判別
        if ($student_score_array[$mid] > $reference_score) {
            //基準点より点数が高かった場合は、生徒の人数から$midの値を引いて、合格者数を算出する
            $result_number = $student_number - $mid;
        } else {
            $flag = false;
            //基準点より点数が低かった場合は、基準点より高いが一番ギリギリだった生徒の番号をループで求める
            while (!$flag) {
                if (isset($student_score_array[$mid])) {
                    if ($student_score_array[$mid] > $reference_score) {
                        $flag = true;
                        $result_number = $student_number - $mid;
                        break;
                    } else {
                        $mid++;
                    }
                } else {
                    $mid++;
                }
                
                //生徒の番号が生徒の数より大きくなってしまった場合→つまり合格者がいなかった場合
                if ($mid >= $student_number) {
                    $result_number = 0;
                    $flag = true;
                    break;
                }
            }
        }
        echo $result_number."\n";
    }
?>
```

# まとめ
久しぶりにアルゴリズムの問題を解いた。
二分探索法も少し忘れつつも、以前勉強したかいあって思い出すための時間はそこまでかからなかった。

A問題を解けるようになるためには、データ数が多い問題に対してアルゴリズムを駆使していかに指定時間内に処理を終わらせるかが重要であるため、引き続き学習していく。
VNCで再ログオンすると進まないとき

不完全な対処法と思われるので忘備録程度

CentOS8へVNCで接続していた際、使い始めようとするとログインするが、一向に画面が切り替わらないことがありました。下の画像ような状態で一向に進まない状態です。

![スクリーンショット 2021-09-23 18.01.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399809/1036c6ae-1865-221b-504a-af2edbc30436.png)
放置しても進まない・・・
vncserverを停止・開始したい衝動に駆られるが、動いているアプリが止まってしまうのでは？と思うとそれもできない・・

検索すると、この方法で解決するという記事を探し出すのでチャレンジ。

```
pkill -HUP gnome-shell
```

お！解除されます。これで解決！！！
と思ったところ、すぐにログオン画面に戻ってしまいます。
何が起きてるかと思いログを確認してみると、

```
less /var/log/messages
```

で以下のようなエラーがでていることがわかります。

```
Could not delete runtime/persistent state file: Error removing file /run/user/0/gnome-shell/runtime-state-LE.:2/screenShield.locked: そのようなファイルやディレクトリはありません
```

```
ls -l /run/user/0/gnome-shell/
```

すると所有者(root)のみフル権限。
ここでJustアイディアで以下を

```
 chmod 777 /run/user/0/gnome-shell/ -R
```
を実行。
なんら変化がない・・・・
やけになってもう一度、

```
pkill -HUP gnome-shell
```

実行すると、今度は解除されたままとなった。

そして、その数時間後、設定を施した同じサーバーで同じ状況に、、、
なんとかの一つ覚えで回避策を実行、


```
pkill -HUP gnome-shell
```

１回でだめなので、２回実行、


```
pkill -HUP gnome-shell
```

めでたく解除！
とりあえず結果オーライ！
フォルダ内のすべてのcsvファイルをpandasで処理

ソースコードを置いているディレクトリ内のすべてのcsvファイルに対して、PandasライブラリのDataFrameで読んで何らかの処理をする方法です。

```Python
import pandas as pd
import glob

files = glob.glob('./*.csv')
    for file in files:
        # csvファイルを試験データを読込む
        df = pd.read_csv(file, encoding='shift_jis’')
        # なにかの処理
```

WindowsのExcelで作成したCSVファイルだとencodingにshift_jisを指定しないと上手く扱えない場合が多いです。
Flutterでバトルシップパズルを作成する4

## 概要
Flutterでバトルシップパズルを作成する
スクリーンサイズと向きを考慮する
効果音を入れる

- [Flutterでバトルシップパズルを作成する3]
(https://qiita.com/iharakenji/items/ff65749c4b6acd1b57d2)

###  実行環境
#### Mac
```sh
$ sw_vers
ProductName:    macOS
ProductVersion: 11.6
BuildVersion:   20G165
```

#### Flutter
```sh
$ flutter --version
Flutter 2.5.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision ffb2ecea52 (5 days ago) • 2021-09-17 15:26:33 -0400
Engine • revision b3af521a05
Tools • Dart 2.14.2
```

## 修正内容
### スクリーンサイズと向きを考慮する
#### スクリーンサイズ、向き、セルサイズを定義する
```dart
late Size _screenSize;
late Orientation _orientation;
static const _cellSizeMax = 40.0;
late double _cellSize;
```

#### スクリーンサイズ、向きを取得してセルサイズを計算する
```dart
@override
Widget build(BuildContext context) {
  _screenSize = MediaQuery.of(context).size;
  _orientation = MediaQuery.of(context).orientation;
  switch (_orientation) {
    case Orientation.landscape:
      _cellSize = [
        _screenSize.width / 18,
        _screenSize.height / 13,
        _cellSizeMax
      ].reduce(min);
      break;
    case Orientation.portrait:
      _cellSize = [
        _screenSize.width / 12,
        _screenSize.height / 19,
        _cellSizeMax
      ].reduce(min);
      break;
  }

  return _buildContainer();
}
```

### 効果音を入れる
こちらで配布している効果音を使わせていただきました
[otosozai.com](https://otosozai.com/)

使用したライブラリ
https://pub.dev/packages/audioplayers

#### 設定を追加
```yml:pubspec.yaml
dependencies:
  flutter:
  audioplayers: ^0.20.1

flutter:
  assets:
    - assets/
```

assets以下に効果音ファイルを置く

```sh
$ tree assets
assets
├── se_saa01.wav
└── se_sad03.wav
```

#### 使い方
```dart
// プレイヤー初期化
final _player = AudioCache(fixedPlayer: AudioPlayer());

@override
void initState() {
  super.initState();
  // 使用するファイルをロードしておく
  _player.loadAll(['se_saa01.wav', 'se_sad03.wav']);
}

// 効果音を鳴らす
if (cellType != CellType.None) {
  // アタリの効果音
  _player.play('se_sad03.wav');
} else {
  // ハズレの効果音
  _player.play('se_saa01.wav');
}
```

## アプリの実行
### アプリを起動
```sh
flutter run
```

### 実行結果
| Android | iOS | macOS | web |
|:-:|:-:|:-:|:-:|
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109450/c2475ae9-ec9d-fc45-7510-80e24c0d64eb.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109450/34e320fc-4518-a58c-c61e-5f8ab256f168.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109450/40ca1fd9-8349-83b9-b7ef-4a49ec74b6bd.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109450/2da5c242-6851-0523-ee7c-6c8549cfe418.png) |

## GitHub
- https://github.com/iharakenji/battleship

### Webアプリ
- https://battleship-74d4f.web.app/
【随時更新】用途別 Cypress辞典

案件でCypressを扱っているが、情報量が少なく
新しく学ぶ人が苦戦しがちであるため、少しずつ自分の知見を共有していきます。
この記事ではテストしたい動作別にcypressの記法を掲載していきます。
なるべく網羅的に記述していきたいところですがすべてを一度に記述するのは大変なため随時更新していきます。
よければLGTM、ストックして更新をお待ち下さい。

## 特定のURLにアクセスする

`cy.visit("path")` を使う

### 例

```ts
cy.visit("http://localhost;:3000") // ルートパスにアクセス
```

なお、ここで記述するURLは `cypress.json` に以下の記述を入れることで簡潔にすることが可能

```json
{
  "baseUrl": "http://localhost:3000",
```

この記述を入れることで、先程の記述は

```ts
cy.visit("/") // ルートパスにアクセス
```

のように書ける

## 要素を取得する

`cy.get` を使う

### 例

```ts 
cy.get('#hoge') // idがhogeの要素を取得
cy.get('.fuga') // classがfugaの要素をすべて取得
cy.get('button span') // buttonタグの子要素のspanタグをすべて取得
cy.get('li.test') // クラス名がtestのliタグをすべて取得
```

### ポイント

引数にはCSSのセレクタと同様の記述が入る

## 要素をクリックする

`cy.get("hoge").click()` を使う

### 例

```ts
cy.get("#hoge").click()
```

なお、click()に引数を渡すことで、要素内の特定の位置を指定してクリックすることも可能

```ts
cy.get("#modal").click("topLeft") // #modalというidの要素の左上をクリック
```

これは上記のように、モーダルの外部をクリックしてモーダルを閉じる動作を検証する際に役立つ

## プルダウンの選択

`cy.get(#hoge).select("fuga")` を使う

### 例

```ts
cy.get("#genre").seleect("test") // テキストが"test"の選択肢をプルダウンから選択
```

## 選択したプルダウンの要素を取得する

`cy.get("#hoge").find(":selected")` を使う

### 例

```ts
cy.get("#genre").find(":selected") // #genreというidが設定されたプルダウンから選択された要素を取得する
```

## 選択したプルダウンのテキストを検証する

`cy.get("#hoge").find(":selected")` で取得した要素を `should(have.text, 'hoge')` で検証する

### 例

```ts
// #genreというidが設定されたプルダウンの選択された要素が"fuga" というテキストを持っていることを検証する
cy.get('#genre').find(":selected").should("have.text", "fuga") 
```

なお、valueを検証する場合は以下。テキストは文字列だけどvalueはid、といったケースもあるので両方使えるようにしておくと良い。

```ts
// #genreというidが設定されたプルダウンの選択された要素のvalueが0であることを検証
cy.get('#genre').find(":selected").should("have.value", 0) 
```

## リクエストのモック
cypressはテストといいつつも、実際にはローカルサーバをプログラムに従って自動操作しているだけなので
APIとの通信部分はモックして実際に通信が走らないようにする必要があります。
これを実現するためには `cy.intercept` というのを使う必要があります。

例

```ts
cy.intercept("GET", "http://localhost:3000/posts", {
  statusCode: 200,
  body: {
    data: [
       {
        id: 1,
        context: "test"
       }
     ]
   }
  }
)
```
このように書くと、GETで `http://localhost:3000` にアクセスした時にステータス200でbody以下のレスポンスを返しますよ
というモックができる。こうすることでフロントで、レスポンスを受け取って次の処理に進むことができる。

エラーを発生させたい場合はstatusCodeプロパティをいじる。
エラーメッセージを画面上に表示したい場合はbodyに適切なエラーメッセージを仕込む

例

```ts
cy.intercept("POST", "http://localhost:3000/posts", {
  statusCode: 422,
  body: {
    errors: ["contentを入力してください"]
   }
  }
)
```

モックする時のポイントとして、画面操作の都合で発生するリクエストは全てモックするということを押さえておきたい。
例えば以下のようにuseEffectでコンポーネント読み込み時に発生するリクエストもモックする必要がある。

```ts
　　useEffect(() => {
    const fetchPostData = async () => {
      const response = await postRequest("fetch")
      if (response.data.data) {
        postDispatch("index", response.data.data)
      }
    }
    fetchGmoPaymentApplication()
  }, [])
```

これは裏を返せば、非同期で走るリクエストを追加するたびにテストコードにモックを追加する必要があるということだ。
特にチームで開発しているときは非同期通信を実装した時に自分が触っていないテストがこける可能性があるので、注意する。
FTPパーミッションdenyをvsftpd設定で直した

[基本環境](#基本環境)
[不具合](#不具合)
[不具合の理由](#不具合の理由)
[不具合を解消](#不具合を解消)
[今後の課題](#今後の課題)
[参考記事](#参考記事)


#基本環境
`CentOS-7.9.2009`
`Apache-2.4.6`
`php-8.0.10`

#不具合
File Zillaで接続するものの、アップロード、ダウンロード、パーミッション変更、削除ができない（つまり見るだけ）
アップロード、ダウンロードファイルの親ディレクトリをパーミッション７７７にするとアップロード、ダウンロードができる

#不具合の理由
`vsftpd`の設定ファイル`vsftpd.conf`内で
`local_umask=022`
という設定をしていたため
この設定では、アップロードするファイルのパーミッションを自動的に下げてしまう
local_umask=022
規定値755を644に下げる


#不具合を解消
vsftpd設定を変更

```:#&nbsp;vim&nbsp;/etc/vsftpd/vsftpd.conf
local_umask=022
↓下記に変更
local_umask=002
```

#今後の課題
###FTPからのパーミッション変更
###sftp接続

***
#参考記事
`https://www.logw.jp/server/7517.html`
`http://park12.wakwak.com/~eslab/pcmemo/linux/vsftpd/vsftpd3.html`
Rails6 + Nuxt.jsでSPAに挑戦する[環境構築]

今日から、Ruby2.6.8　Rails6　Nuxt.jsの組みあわせでポートフォリオ作成に挑戦します。

まず前提として、環境は
Windows Subsystem for Linux 2にUbuntu20.04LTSを
載せた状態になります。

フォルダ構成は、
(ubuntuホームディレクトリ)/environment/appname
です。ワークスペースを作ってわかりやすくしたかったので、mkdirでenvironmentを作っています。

```sh
#ubuntu CLI
rails new [appname] --database=postgresql --skip-bundle --api
```

[appname]部分は、カッコも含めて外して任意の名付けをして下さい。
apiモードでアプリを新規作成し、DBはPostgres使用です。
（Postgresのロール作成・PASS設定などは割愛します。）

```sh
#ubuntu CLI
sudo /etc/init.d/postgresql start
```
でデータベースを起動して、

```sh
#ubuntu CLI
bundle install
rails db:create
# (rails serverでもOK)サーバー起動
rails s
```
DBのロール作成、ログインができていれば、
ブラウザでlocalhost:3000に移動して、Railsの初期ロゴ画面が見えているはずです。

次に、Nuxt.jsをyarnを使ってRailsアプリの中にインストールします。

```sh
#ubuntu CLI
yarn create nuxt-app [appname]
```
僕の場合、Nuxt構成時は以下のように選択しました。

```sh
#ubuntu CLI
✨  Generating Nuxt.js project in f_Idea
? Project name: f_Idea
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Testing framework: None
? Rendering mode: Single Page App
? Deployment target: Server (Node.js hosting)
? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? What is your GitHub username? yourname
? Version control system: Git
```
Press <space> to select ~ となっている部分は選択なしで進んでいます。
これが完了してから、

```sh
# [appname/nuxt.config.js]
export default {
  server: {
    port: 8080
  },
# 以下はNuxtインストール完了時と変えていないので省略
```
rails側のlocalhostポートと衝突するので、Nuxt側のポートを8080に変更します。ここまでやると、

```sh
#ubuntu CLI
cd　[appname] #アプリのフォルダへ移動
yarn dev #Nuxt.js起動
```
localhost:8080にアクセスすると、Nuxt.js/Vue.jsのロゴが出ているはずです。

今回は、環境構築部分のみです。キリがいいので、今回はここまでです。お疲れ様でした。
Excel VBA アクティブブック シート名一覧をマクロ実行ブックに転記

```vb
Option Explicit
Sub main()
  Dim tWB As Workbook
  Dim wdS As Window
  Dim mNL As Collection
  Dim str As Variant
  Dim arrStr as String
  Dim i As Long
    Set mNL = makeAllSheetNameList()
    Set tWB = ThisWorkbook
    Set wdS = tWB.Windows(1)
    i = 1
      'マクロ実行ファイルのシート1に転記
　　  For Each str In mNL
        if i = 1 then arrStr = str
        if i > 1 then arrStr = arrStr + "," + str
        i = i + 1
      Next
    tWB.Worksheets(1).Range("A" & i) ="array(" & arrStr & ")"
    wdS.WindowState = xlMaximized
    'MsgBox "完了", vbOKOnly, "メッセージ"
End Sub
```
```vb
Function makeAllSheetNameList() As Collection
  'アクティブブックのシート名をコレクションに詰めて返す
  Dim i As Variant
  Dim nameList As Collection
    Set nameList = New Collection
      For Each i In Sheets
          nameList.Add (i.Name)
      Next
    Set makeAllSheetNameList = nameList
End Function
```
【メモ】SpringアプリケーションでHTTPSを有効化：自己証明書を作成

実際にやってみたときのメモと、そもそもを理解できてなかったのでまとめためもです。

#### そもそもの話
SSLって何？とかは、以下参照。
[【勉強メモ】SSL/TLSとhttp/httpsの違い - Qiita](https://qiita.com/43z335/items/7e9252071392de0c385c)


#### 前提事項
* アプリはSpringBoot（2.4.3）で実装。
* アプリサーバはAWSのEC2で稼働。

### 作業の流れ
1. アプリサーバ上で、自己証明書を作成（keytoolコマンド利用）
1. SpringのプロパティでSSL関連の設定を定義
1. アプリを稼働させてhttpsでリクエスト

# 手順
## SSL証明書の発行

```
$ keytool -genkeypair -alias tomcat
 -storetype PKCS12 -keyalg RSA -keysize 2048
 -keystore keystore -validity 3650

Re-enter new password:
What is your first and last name?
  [Unknown]:  
What is the name of your organizational unit?
  [Unknown]:  
What is the name of your organization?
  [Unknown]:  
What is the name of your City or Locality?
  [Unknown]:  
What is the name of your State or Province?
  [Unknown]:  
What is the two-letter country code for this unit?
  [Unknown]:  
Is CN= , OU= , O= , L= , ST= , C=  correct?
  [no]:  yes

Enter key password for <tomcat>
        (RETURN if same as keystore password):
Re-enter new password:
```

|オプション|説明|
|:--|:--|
|-genkeypair|公開鍵と秘密鍵の生成。`mykey`(デフォルト)|
|-alias|格納する新しいキーストアエントリ。|
|-storetype|インスタンスを生成するキーストアのタイプ。<br>（プロパティファイルの「keyStoreType」の値）|
|-keyalg|鍵生成時に使うアルゴリズム。`DSA`(デフォルト), `RSA`, `DES`, `DESede`|
|-keysize|生成する鍵のサイズ。`1024`(デフォルト)|
|-keystore|キーストアの場所。デフォルトはユーザーホームディレクトリ。|
|-validity|証明書の有効日数。`90`(デフォルト)|

* [keytool - 鍵と証明書の管理ツール](https://docs.oracle.com/javase/jp/6/technotes/tools/windows/keytool.html)

## 登録した証明書の確認
`keytool`の`-list`で確認できる。

```
$ keytool -v -list -keystore .keystore

Enter keystore password:
Keystore type: jks
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: tomcat
Creation date: Aug 3, 2021
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Issuer: CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown
Serial number: xxxxxxxx
Valid from: Tue Aug 03 09:06:54 UTC 2021 until: Mon Nov 01 09:06:54 UTC 2021
Certificate fingerprints:
         MD5:  00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
         SHA1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
         SHA256: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
Signature algorithm name: SHA256withDSA
Subject Public Key Algorithm: 2048-bit DSA key
Version: 3

Extensions:

#1: ObjectId: 0.0.00.00 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: ～
0010: ～
]
]
```

## HTTPSの有効化

```properties:application.properties
# SSL証明書を保持するキーストアへのパス（※作成したkeystoreのパス＋ファイル名）
server.ssl.key-store=keystore
# キーストアにアクセスするためのパスワード
server.ssl.key-store-password=[SSL証明書作成時に設定したパスワード]
# キーストアのタイプ
server.ssl.key-store-type=PKCS12
# キーストア内のキーを識別するエイリアス
server.ssl.key-alias=tomcat
```

[Spring Boot アプリケーションプロパティ設定一覧 - リファレンス](https://spring.pleiades.io/spring-boot/docs/current/reference/html/application-properties.html)

## HTTPSでリクエスト実行
SpringBootアプリケーションを起動させて、httpsでリクエストする。


## 参考サイト
[Spring bootでSSL（HTTPS）を有効にする - Qiita](https://qiita.com/keigohtr/items/001b84838fefcc170ea2)
Go のキャストが難しい

# これは何？

Go のキャストが難しいなと思う事例があったので紹介する。

# 事例

ちょっと長いけど、まあソースコード。

```go:go
package main

import "log"

type hoge interface {
	foo() string
}

type fuga struct {
	hoge
}

type piyo struct{}

func (h *piyo) foo() string {
	return "piyo"
}

func main() {
	f := &fuga{hoge: &piyo{}}
	test := func(h hoge) {
		p, ok := h.(*piyo)
		log.Println(h.foo(), p, ok)
	}
	test(f)      //=> piyo <nil> false
	test(f.hoge) //=> piyo &{} true
}
```

このコードの

```go:go
log.Println(h.foo(), p, ok)
```

の部分。
`h.foo()` が `func (h *piyo) foo() string` を呼べてるんだから、 `h` から `piyo` へのポインタって取れそうなもんだと思うんだけど、 `test(f)` の中だと `h.(*piyo)` が失敗する。

詳細な言語仕様を把握してないんでなんでキャストできないのかはわからないんだけど、難しいね。

```
var h hoge = &fuga{hoge: &piyo{}}
```

という形で手に入れた `h` から `piyo` へのポインタを手に入れるいい方法がよくわからない。

```go:go
ppiyo, isPiyo := func(h hoge) (*piyo, bool) {
	if f, fok := h.(*fuga); fok {
		if p, pok := f.hoge.(*piyo); pok {
			return p, true
		}
	}
	return nil, false
}(h)
```

とやれば取れるけど、こんなに書かないとだめ？

まあ一般論としてはキャストが不要な設計が良い設計だと思うので、そんなことが必要な場面を作らないのが正義だとは思う。
【未経験】テックキャンプを卒業し、全体を通しての感想

11月中旬より、テックキャンプ夜間90期生としてスタートし、今年6月に卒業。
転職活動約3ヶ月を経て無事に内定を頂け、
入学から内定までの感想をまとめたいと思います。

#結果どこが良かったか
###１.エンジニアとしての基礎学習から、アプリ作成までのルートがしっかりしている
もともと私は、PC関連や、その他周りに基礎知識があったりしたため、振り返りになる部分が多かったですが、あまり知識が少ない、どういったルートでプログラミングを学んで行けばいいかが詳しくない方でも、しっかりとした学べるルートが確約されているので、迷うことなく淡々と進めていくことができます。

Webアプリケーションが動く流れや、理由も詳しく学べ、ネットでも探せば載っている内容も多々ありますが、最短で知識をつけるには、効率よく学ぶことができるので、すぐにエンジニアになりたい方は非常におすすめです。

また後述する内容と被ってしまいますが、ライフコーチ等のサポートが手厚く、困った際や些細な悩みでも、真摯に対応してくれ、躓くことがあってもすぐに立て直せます。
そういったカリキュラムでの内容や、担当してくれるスタッフ含めて、学習する上で学びやすい環境が整っていると思います。

###２.ライフコーチ・メンター・キャリアアドバイザーのサポートが充実
独学でプログラミングを学習する際、一番挫折やキツいと感じることは、わからないことが起きた時の解決方法と、相談する相手がいなく、1人で抱え込んでしまうことにあると思います。
もともとパイプを持っている人や、外への発信をしてきた人であれば、問題なくこなしてしまうのかと思いますが、誰しもがそういった環境ではない中、相談や、悩みの解決を一緒になって行ってくれるスタッフが近くにいることで、そういった挫折部分を軽減させてくれます。

どのような悩みであっても真摯に受けとってくれ、決して適当な解決はせず、時間をかけてでも対応してくれ、スタッフの厚みを学習中は常に感じていました。

特にアプリでのエラーが発生した時は、簡単に答えや解決できるアドバイスをするだけでなく、どういったことが起きていて、どのようなことをすれば解決に近づけるのか。を一緒に考えてくれ、次に同じようなエラーが起きてしまっても、対応おできるスキルをつけられる方法で答えてくれ、相談することでより自分のスキルが上がっていく実感を得ました。

またキャリアアドバイザーの方は、転職する上での必要書類のカバーや、常に転職状況を気にされた中、色々とアドバイスを多く頂け、厳しい転職活動の最中でも挫折することなく内定まで行けたと思います。

###３.一緒に学ぶ仲間が増える
同じ９０期生と方々と、同じslackでの環境で学びの共有や、情報共有をしていた関係で、自分の知らない知識や、問題部分も一緒に考える環境にあったため、非常に仲間意識を持つことができました。

同じエンジニアを目指して学んでいる方々のため、非常に仲間意識を感じ、困ったことや自分の知った情報を他の人にも教えたい！という気持ちになり、情報交換の場を多く設け、キツい環境下でも励みとなり心強かったです。

#デメリット
###１.料金が高い
私は現職を継続したままでの入学だったため、やはり金額は他のスクールと比べて高かったです… 
ただ事前にその情報を知った上で、テックキャンプを選んだ理由は、
転職する上でのサポートと、転職支援の範囲の制限がない。と、転職を絶対に考えていたため、
覚悟の上で入学を決めました。

また、必要PCでMacの所持が必須だったので、Macを持っていない人はその分の費用も重なってくるので、
金銭的に厳しい部分はあるかと思います。
ただ、入学してからも、金額面で物足りなかった部分はほとんど感じられず、実際にいきたい企業に転職もできているので、将来を考えれば、必要投資の一部なので、結果プラスと考えています。

###２.安易な気持ちで入学すると、厳しい
やはり技術職ということもあり、生半可な気持ちでは、続かないと感じます。
実際プログラミングを学び、覚悟を持っていれば誰でもできる内容と思いますが、簡単な考えや、エンジニア給与が高いからなどの安易な気持ちだと、学習がしんどくなり、途中挫折すると思います。
本気でエンジニアを目指したいという気持ちが無ければ継続は厳しいと思います。

#未経験からの転職活動について
やはり未経験という部分で、書類選考の時点で通らない部分が多々ありました。
卒業後も継続して新たにポートフォリオや、技術を磨いていかないと、
入りたい企業様へは到底就職できないと思います。

私はテックキャンプ卒業から、転職活動中もポートフォリオ作成を継続しており、
常に学習中ということをアピールしつつ、Gitに更新を継続しておりました。
企業の方はやはりGitを多く見られるので、そこを怠らずに、企業にアピールしておりました。

#まとめ
以上が全体を通しての流れでございます。
受講料は確かに金額として高かったですが、その分身についたこと、プラスになったことが多く、
やはり今でもテックキャンプに入学していて良かったと思います。
検討されている方は、本気でエンジニアを目指したいのであれば、非常におすすめいたします。
WSL2(Ubuntu20.04LTS) で untrunc を使いMP4動画を復元する

MP4ファイルが壊れてしまったので untrunc(WSL2/Ubuntu20.04LTS) を使って修復した。
untrunc は GitHub で公開されているMP4修復ツールだ。
破損したMP4とソースを同じくする正常なMP4ファイルさえあれば、それを元にMP4を修復してくれる。

　インストールしたてのWSL2上のUbuntuではコンパイラや前提となるライブラリが存在しないのでそれらのインストールから行う。またLibavが必要なため公式サイトから拾ってくる。

```bash
cd
sudo apt install make git gcc g++ yasm nasm zlib1g-dev
git clone https://github.com/ponchio/untrunc
wget https://libav.org/releases/libav-12.3.tar.gz
tar xvzf libav-12.3.tar.gz -C untrunc
```
　この時 untranc ディレクトリ内に libav-12.3 として解凍されるのだが、これだと上手くいかないので元々あったlibavディレクトリ(中身は空)を削除してからディレクトリをリネームする。

```bash
cd untrunc/
rm -r libav/
mv libav-12.3/ libav/
cd libav/
./configure
make
```

Libav がコンパイルされるので上位ディレクトリに戻って untranc をビルドする。

```bash
cd ../
g++ -o untrunc -I./libav file.cpp main.cpp track.cpp atom.cpp codec_*.cpp codecstats.cpp codec.cpp mp4.cpp log.cpp -L./libav/libavformat -lavformat -L./libav/libavcodec -lavcodec -L./libav/libavresample -lavresample -L./libav/libavutil -lavutil -lpthread -lz
```

これで untrunc ディレクトリ内に untranc が生成された。

```bash
./untrunc <正常なMP4>.mp4 <破損したMP4>.mp4
```
untrunc にMP4を食わせるだけで修復され、MP4が無事再生できるようになった。めでたしめでたし。
Elixirからプログラミングを始める人向けリンク集

## 内容
昔なつかし？リンク集

## 本記事の対象
Elixirからプログラミングを始める人

## インストール方法
公式が最強
https://elixir-lang.jp/install.html

## 入門書
紙の本・電子書籍両方あります。

https://www.ohmsha.co.jp/book/9784274226373/

## 入門用記事

### fukuoka.exイチオシ
Excelから！

https://qiita.com/piacerex/items/6714e1440e3f25fb46a1

### Elixir School
これが全部ではないけど
基本〜Mixまでをある程度理解していれば
webのElixirやPhoenix記事はなんとか読めるようになる

基本 数字や文字列、+-*/の扱いとか

https://elixirschool.com/ja/lessons/basics/basics/

コレクション 他の言語で言う配列とかマップとか

https://elixirschool.com/ja/lessons/basics/collections/

Enum コレクションを扱うモジュール

https://elixirschool.com/ja/lessons/basics/enum/

パターンマッチング

https://elixirschool.com/ja/lessons/basics/pattern-matching/

制御構造 パターンマッチングに慣れると使わなくなってくるもの

https://elixirschool.com/ja/lessons/basics/control-structures/

関数 匿名関数と名前付き関数の作り方

https://elixirschool.com/ja/lessons/basics/functions/

パイプ演算子 使い慣れるととても便利

https://elixirschool.com/ja/lessons/basics/pipe-operator/

モジュール コードの量が増えた時に読みやすくする書き方

https://elixirschool.com/ja/lessons/basics/modules/

Mix　プロジェクトと言う本格的なプログラムを書く時のディレクトリとファイルのかたまりを扱うもの

https://elixirschool.com/ja/lessons/basics/mix/

## 参考記事
### Enum

https://snamiki1212.com/elixir-enum-master

https://angelika.me/elixir-enum-cheatsheet/

### その他
英語が読めるなら面白い記事

https://thoughtbot.com/blog/is-elixir-a-scripting-language
rex0220 アクション表示制御プラグイン

計算式でアクションボタンの表示制御を行うプラグインです。

主な機能
・計算式でアクションボタンの表示制御
・アクションボタンの色指定機能
・３ヶ国語対応
・PC・モバイル対応

Ver.14
・DIC_MAP 関数を追加
・EV_INFO 関数に、appId オプション追加
・APP_URL, LOOKUP_GETID, RELATED_GETID 関数追加
・TABLE_DATA, TABLE_MAP, TPDIC 関数追加
　TABLE_DATA(TABLE_MAP(テーブル1,
　TPDIC("ドロップダウンT2",ドロップダウンT1, "数値T2",数値T1, "金額T2", 単価T1*数量T1)))
・プラグイン設定画面初期処理でエラー発生時に、ダイアログ表示するように変更
・kintone.Promise を Promise に変更

[rex0220 stores](https://rex0220.stores.jp/)で、販売中です。

参考：
- [rex0220 アクション表示制御プラグイン アクションボタンの色を変えてみよう](https://qiita.com/rex0220/items/e0ea47359147897f8604)
- [rex0220 アクション表示制御プラグイン ログインユーザーが組織選択の所属か判定](https://qiita.com/rex0220/items/45ebf2d1e8dfa5e237fa)


# アクションボタンの表示制御

ステータスによるアクションボタンの表示制御例です。
ステータスが「処理中」で、「テスト１」のアクションボタンを表示

![2021-09-23_16h55_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/616146e2-4e24-1b33-9caa-bcbaa8e0499a.png)

![2021-09-23_17h18_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/867e7442-7926-fd59-218e-30e3ca8b4009.png)

# アクションボタンの色設定例

![2022-04-07_08h54_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/02632919-1a8c-637c-c671-fce84c515dd1.png)

![2022-04-07_08h55_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e101060f-3847-7a3d-bf91-5bdd30211626.png)

![2022-04-07_08h56_54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/6453929c-b2ce-e74a-10a3-b62f8c3c569d.png)

# プラグインのインストール

- kintone システム管理> その他> プラグインを開きます。

![2022-07-01_18h47_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/54799002-6b37-3d34-dd6a-cc8c33e3ebea.png)

- プラグインファイルを読み込みます

STORES からダウンロードまたは購入したプラグインファイルを kintone に読み込みます。

![2022-07-01_18h41_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/bdb5ad1c-d1ff-7b78-6a68-d02ae79ccc81.png)

- アプリへのプラグイン追加

対象アプリの設定画面で、アクション表示制御プラグインを追加します。

![2022-07-01_18h49_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4c66048d-7c35-eb4f-977b-b328d9c94a57.png)


# プラグインの設定例
計算式の実行結果が true の場合、アクションボタンが表示されます。
計算式には、[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)の関数を指定できます。

- アクション名：複写
    - IN(ステータス,"未処理","処理中")
- アクション名：テスト1
    - AND(ステータス="処理中",顧客ランク="A")
- アクション名：テスト2

チェックしない場合は、ボタン表示
![2022-04-07_08h42_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/1a1ef6d8-bb5c-81d7-9c43-547dea5315a9.png)

# ボタンの色指定

- テーマ：　カラーパレットで選択すると、文字色と背景色がまとめて設定されます。
- 文字色：　カラーパレットで選択すると、文字色が設定されます。
- 背景色：　カラーパレットで選択すると、背景色が設定されます。

![2022-04-07_08h47_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2c358626-23a2-ce13-cb81-6f56eec795fe.png)

テーマの選択
![2022-04-07_08h48_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c303bc61-170f-e892-fa1b-4c7d46f7a356.png)

文字色、背景色の選択
![2022-04-07_08h52_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3e6bfe33-5b8c-9cc1-9271-7d5b8a199bc5.png)

# 注意事項

- 既に、JavaScript によるカスタマイズを行っているアプリの場合、処理が競合して、エラーになる場合があります。その場合は、該当するアプリでプラグインの使用を中止してください。
Ubuntuのターミナルで名前付きタブを複数生成

## 参考

https://askubuntu.com/questions/277543/opening-multiple-tabs-with-gnome-terminal

## 環境

- Ubuntu 20.04

## コード

terminalで作業するために毎回 git, docker用のタブを一個ずつ開いて、、、というのが面倒だったので自動化してみました。

```test.sh
gnome-terminal --tab --title="dcu"

gnome-terminal --tab --title="yarn"

gnome-terminal --tab --title="ngrok"

gnome-terminal --tab --title="copyq"

gnome-terminal --tab --title="git"

gnome-terminal --tab --title="mysql container"

gnome-terminal --tab --title="golang container"

```

このシェルスクリプト一個で上記のタブを名前付きで開くことが可能です。
discord.js/buildersのoption設定で出るArgumentErrorについて

#コード
```
const { SlashCommandBuilder } = require('@discordjs/builders');

module.exports = {
    data : new SlashCommandBuilder()
        .setName("add")
        .setDescription("---")
        .addIntegerOption(option=>
            option.setName("A")
                .setDescription("---")
                .setRequired(true)),
    async execute(interaction){
    }
```


#エラー内容
```
 throw new argument_error_1.ArgumentError(message, main, errors);
            ^

ArgumentError: Expected string `name` to be lowercase, got `A`
    at Object.ow [as default]

```

#解決方法
option.setNameに大文字や英語以外を入れるとエラーが出ます。英語の小文字を入力するようにしましょう。
Poetryでwhl does not existとなる問題への対処

# 環境
Windows 10 Pro
Python 3.9.7
Poetry 1.1.10

# 問題点
poetryを導入後、`poetry install`や`poetry add`、`poetry self update`などを行おうとすると

```
Package operations: 10 installs, 0 updates, 0 removals
  • Installing pyparsing (2.4.7)
  ValueError
  File \C:\Users\usr\AppData\Local\pypoetry\Cache\artifacts\92\0f\cf\(略)\pyparsing-2.4.7-py2.py3-none-any.whl does not exist

  at ~\.poetry\lib\poetry\_vendor\py3.9\poetry\core\packages\file_dependency.py:40 in __init__
       36│             except FileNotFoundError:
       37│                 raise ValueError("Directory {} does not exist".format(self._path))
       38│
       39│         if not self._full_path.exists():
    →  40│             raise ValueError("File {} does not exist".format(self._path))
       41│
       42│         if self._full_path.is_dir():
       43│             raise ValueError("{} is a directory, expected a file".format(self._path))
       44│
```
とエラーとなります。

# 原因
[Poetryのissue4479](https://github.com/python-poetry/poetry/issues/4479)に同様の問題が上がっていました。
パスの表記方法がWindowsを考慮せず、先頭にバックスラッシュ(\\)が入ってしまうのが原因とのこと。
確かにエラーメッセージでも`\C:\Users\usr\AppData~`とCの前にバックスラッシュが入ってしまっています。

# 解決策
[Pull Request](https://github.com/python-poetry/poetry/pull/4549)がされているようなので、そのうち修正されるのではないかと思います。
すぐに解決したい場合は、以下の手順でPull Requestと同じようにコードを修正することで直りました。

- poetryがインストールされているフォルダ(デフォルトだとC:¥Users¥ユーザー名¥.poetry)の`poetry/installation/executor.py`(C:¥Users¥ユーザー名¥.poetry¥lib¥poetry¥installation¥executor.py)をテキストエディターで編集
- [追記]自分の環境では上記にexecutor.pyがありましたが、`C:\Users\<username>\AppData\Roaming\pypoetry\venv\Lib\site-packages\poetry\installation\`にある場合もあるようです。

- importの14行目に`from poetry.core.packages.utils.utils import url_to_path`を追加

```python:executor.py(変更前)
 from poetry.core.packages.file_dependency import FileDependency
 from poetry.core.packages.utils.link import Link
 from poetry.core.pyproject.toml import PyProjectTOML
```
↓

```python:executor.py(変更後)
 from poetry.core.packages.file_dependency import FileDependency
 from poetry.core.packages.utils.link import Link
 from poetry.core.packages.utils.utils import url_to_path # <- 追加(14行目)
 from poetry.core.pyproject.toml import PyProjectTOML
```

- 620行目(上を既に追加してる場合621行目)の`Path(archive.path)`を削除するかコメントアウトし、`url_to_path(archive.url)`へ変更


```python:executor.py(変更前)
FileDependency(
    package.name,
    Path(archive.path)
    if isinstance(archive, Link)
    else archive,
).hash(hash_type),
```
↓

```python:executor.py(変更後)
FileDependency(
    package.name,
    # Path(archive.path) # <- 削除するかコメントアウト(620or621行目)
    url_to_path(archive.url) # <- 追加
    if isinstance(archive, Link)
    else archive,
).hash(hash_type),
```
[Rails]controllerのストロングパラメータとは

##初めに
####なぜこの記事を書きたかったのか
requireは何を指定してるのかわからなくなったので、ストロングパラメータの再確認をするためにメモしたい！

####環境
・Macbook Air (Retina, 13-inch,2019)
・プロセッサ 1.6GHz デュアルコアIntel Core i5
・メモリ　8GB 2133 Mhz LPDDR3
・MacOS Big Sur　バージョン 11.5.2

####記事の目次
**１）ストロングパラメータってなんぞ？**
**２）どうやって使うの？**
**３）最後に**

##ストロングパラメータってなんぞ？
**controller内に新たに作成したメソッド名に取得したい情報を指定することができる**

##どうやって使うの？
####1)controller内のアクションの命令式にストロングパラメータに使うメソッド名を追加する。(今回はorder_paramsとする)
**(例えば)通販サイトにuserが商品の届け先を記入しなければならないページがあるとする。その個人情報を保存するときcreateアクションで処理する。商品の届け先の記入欄に郵便番号（zip_code）、住所(adress)、ビル名(buiding_name)、電話番号（phone_number）のみをDBに保存したい場合**

**(下記の例用のテーブル）**
![sampletable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102030/e3c306eb-e340-eaf6-135b-0fa9a421bc5d.png)

```ruby
（コントローラー）
def create
  ＠purchase_order　= PurchaseOrder.new(order_params) 
end
```
####２）追加したメソッドに保存したいカラムを指定する

```ruby
（書き方）
private

def メソッド名
  params.require(:どこのハッシュを参照すればいいか判断).permit(：requireで指定した場所のなんのカラムの取得したいか指定).merge(他に追加したいハッシュを指定)
end
```


```ruby
（コントローラー）
def create
  ＠purchase_order　= PurchaseOrder.new(order_params) 
end

private

def order_params
  params.require(:purchase_order).permit(:zip_code, :address, :building_name, :phone_number).merge(user_id: current_user.id)
end
```
**※require(:purchase_order)でpurchase_order内の配列を指定**
**※permit(:zip_code, :address, :building_name, :phone_number)でカラム内の郵便番号、住所、ビル名、電話番号を保存してくださいと命令できる**
**※merge(user_id: current_user.id)でuser情報も取得してくださいと設定**

##最後に
実際実装をするとき、修正＆エラーで作成してもっとも近い正解を探して制作できるけど、実際こういう場で自分が作業したことを言語化するとわかった気でいただけなんだなって認識させられちゃう（汗）反復練習と言語化が大事だ！

ココまで読んでくださいましてありがとう！
【rails】 存在しないデータにアクセスした時の例外処理

# レコードに存在しないデータにアクセスした

作成したコントローラーに

```profile_controller.rb
class ProfilesController < ApplicationController

  def show
    @profile = Profile.find(params[:id])
  end

end
```
とだけ書いて適切な例外処理を書いていない場合、存在しないデータのURLにアクセスしようとすると
![スクリーンショット 2021-09-23 14.06.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1067124/0184b12f-bfba-fd95-8d5e-f7de0e42c37d.png)
ActiveRecord::RecordNotFoundというエラーが出てしまいます。
このようにレコードにデータが存在しない場合の例外処理を書いて行きます。

# rescueを用いた例外処理
`rescue`を使うと、エラーが発生した場合次に行う処理を書くことができます。
今回、プロフィールコントローラーで発生したエラーを処理して行きます。
idを指定しクエリ実行後、レコードにそのパラメーターをもつデータが存在しない場合にプロフィールのindexページにリダイレクトされるような処理を`rescue`を用いて書きます。

```profile_controller.rb
class ProfilesController < ApplicationController

  def show
    @profile = Profile.find(params[:id])

    #以下を追記
    rescue ActiveRecord::RecordNotFound => e
    redirect_to profiles_path
  end

end
```
この記述によってプロフィールコントローラーのshowアクションがデータベースからデータを取得する処理を実行し、ActiveRecord::RecordNotFoundというエラーがでてもプロフィールのindexページにリダイレクトされるようになりました。

# rescue_fromを用いた例外処理
`rescue_from`は、例外を1つのコントローラ全体で扱えるようになります。
すなわちshowアクションの他に、edit、update、deleteでも同じ処理をしたい場合

```profile_controller.rb
class ProfilesController < ApplicationController
#以下を追記
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  def show
    @profile = Profile.find(params[:id])
  end

  def edit
    @profile = Profile.find(params[:id])
  end
#省略
#以下を追記
  private

  def record_not_found
    redirect_to profiles_path
  end

end
```

このように処理を書くことで、プロフィールコントローラーのデータを取得する処理を実行するアクションから存在しないデータにアクセスした場合、indexページにリダイレクトされるようになります。