OmniAICreator/Qiita-1.07M huggingface dataset:
pathの引数について

Rspecでテストを書いているとき、下記の実装に関してpathの引数に`task.project`が使われていることに疑問を感じておりました。

```ruby
describe 'Task詳細' do
  context '正常系' do
    it 'Taskが表示されること' do
      visit project_task_path(task.project, task)
      #project_task_path(project, task) ではだめなの？
      expect(page).to have_content(task.title)
      expect(page).to have_content(task.status)
      expect(page).to have_content(task.deadline.strftime('%Y-%m-%d %H:%M'))
      expect(current_path).to eq project_task_path(task.project, task)
    end
  end
end
```

#前提条件
taskとprojectがassociationの関係を持つ。

```ruby
class project < ApplicationRecord
  has_many tasks
end
```
```ruby
class Task < ApplicationRecord
  belongs_to :project
end
```

#考え方
まず考えるべきなのが、どのようなURLが生成されるべきかということ。

ここではTaskの詳細画面なのでURL`/project/id/task/id/show` となるべきですね。

次にtaskとprojectがassociationの関係を持つということ。

```ruby
class project < ApplicationRecord
  has_many tasks
end
```

```ruby
class Task < ApplicationRecord
  belongs_to :project
end
```

これによりtaskはproject(親)のidを持つことになります。

実際にpathの引数のレコードを調べるとこんな感じ。

```ruby
(byebug) project
#<**Project id: 1**, name: "dolorum", status: "todo", release_date: "2019-05-24", created_at: "2021-06-28 14:23:59", updated_at: "2021-06-28 14:23:59">
(byebug) task
#<Task id: 3, title: "Task", status: "done", deadline: "2019-10-17 15:00:00", completion_date: nil, description: nil, **project_id: 2**, created_at: "2021-06-22 10:38:01", updated_at: "2021-06-22 10:38:01">
(byebug) task.project
#<**Project id: 2**, name: "repudiandae", status: "todo", release_date: "2019-11-05", created_at: "2021-06-22 10:38:01", updated_at: "2021-06-22 10:38:01">
```

注目すべきは`project_id` ****の値。

`project_id: 1`に対しtaskは`project_id: 2`を持っていますね。

これはassociationの関係とは言えません。

実際`project_task_path(project, task)`でもURL自体は生成されますが、これでは`project_id`が異なるため、生成されるURLのidはassociationの関係ではなくなってしまいます。

```ruby
project_task_path(project, task)
=> /project/1/task/3
```

`project_task_path(task.project, task)`のようにしてproject(親)のidを`task.project`の返り値から取得することで、生成されるURLはassociationの関係を保つことができます。

```ruby
project_task_path(task.project, task)
=> /project/2/task/3
```

#引数の順番を入れ替てみる
以下のような結果から、pathの引数はassociationで定義したことなど関係なく、引数に指定した順番の通りにidを渡すようです。

```ruby
project_task_path(task.project, task)
=> /project/2/task/3

# 引数の順番を入れ替えた結果
project_task_path(task, task.project)
=> /project/3/task/2
```

なので、引数を指定する際は定義したassociationの関係や、実際のブラウザの挙動を意識して、引数を指定してあげる必要があります。
class・idの複数指定

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="KKqNbJb" data-user="paripi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/paripi/pen/KKqNbJb">
  qiita</a> by tomoe (<a href="https://codepen.io/paripi">@paripi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

同じタグにidを複数指定は、、

- エラーにはならない（表示されないとかにはならない）
- 文法的には誤り
- CSSが思い通りに適用されない


【参考】
[HTMLで同じタグに複数のid属性を指定することはできる？](https://qumeru.com/magazine/1)
python Yahooニュースの指定したワードのみをスクレイピング


yahooニュースをいちいち確認するのが面倒と思ったので、Webスクレイピングを使ったプログラムを書いてみました。

今回は、`コロナのニュースを表示させる`ものとなっています。


```python:

from bs4 import BeautifulSoup
import requests as req
import pandas as pd
import re

# 処理をクラスにまとめる   
class List:
    
    #コンストラクタにURL+ページの数を呼べるようにする
    def __init__(self, page):
        self.url = "https://news.yahoo.co.jp/topics/top-picks?page="+str(page)
    
    #以下処理メソッドをまとめる
    def yahoo_s(self):
        
        #ヤフーニュースの情報を取得する
        res = req.get(self.url)
        #print(res)
        
        #BeautifulSoupにヤフーニュースのページ内容を読み込ませる
        yahoo_html = BeautifulSoup(res.text,'html.parser')
        #ヤフーニュースのタイトルとURLの情報を取得する
        news_list = []
        url_list = []
        data_list = yahoo_html.find_all(href=re.compile("news.yahoo.co.jp/pickup"))
    
        #ヤフーニューズのタイトルをリストに格納
        for yahoo_data in yahoo_html.select('.newsFeed_item_title'):
            news_list.append(yahoo_data.string)
        # print(news_list)
        return news_list


#二次元内包表記にてリストに格納
all_list = []
all_coronalist = []
for i in range(10):
    page = List(page=i+1)
    plist = page.yahoo_s()
    all_list.append(plist)
    
    #リスト内の,コロナに関係するワードのみを格納
    l_in = [s for s in plist if 'コロナ' in s or '感染' in s]

    all_coronalist.append(l_in)

#print(allcoronalist)

#二次元リストを一次元にして格納
all_corona_news = sum(all_coronalist, [])

#データフレーム
title_list_corona = pd.DataFrame({'Title':all_corona_news})

title_list_corona

```

取得したニュースをデータフレームに格納して、それをフォルダにCSVにして保存するプログラムです。
今回は、合計11件のニュースになっていますが上限は決めておらず、「`#二次元内包表記にてリストに格納`」のforループした範囲のすべてを取得するものになっています。

↓が今回のデータフレームです。
![data_ff.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1958183/ff2578ad-db37-3225-8e38-20b5916f6e01.jpeg)

##LINEに取得したタイトルを送る

```python:
#取得したトークン
Token = 'afUaL44902wfil2Xshx4bd53sYpb47CSygCAuISpjc4'
#APIのURL
api_url ='https://notify-api.line.me/api/notify'
#通知内容
send_title = all_corona_news


#情報を辞書型にする
Token_dic = {'Authorization':'Bearer' + ' ' + Token}
send_dic = {'message': send_title}
print(Token_dic)
print(send_dic)

#LINE通知を送る(200: 成功時、400: リクエストが不正、401: アクセストークンが無効: 公式より)
#()内は、アクセスするWEB APIのURL、認証情報、送りたい内容
req.post(api_url, headers=Token_dic, data=send_dic)
```
こちらとWindowsのタスクスケジューラを使い**決まった時間に、LINEでニュースをチェックできる**ようにしました。


###工夫した点

- ニュースの中から特定のワードのみを取得するプログラムが書けたこと。
- **他のワードにも対応できる**書き方が出来たところ。

###妥協点
- 本当はURLも一緒に取得したかったのですが、指定したタイトルのURLのみを取得することが出来なかった点。
- 思っていたよりコードが長くなってしまった点。
- LINEに送るとき、データフレームの綺麗な状態で送りたかったが、それが出来なかったので、一次元リストにして送ることにしたので、文字列が綺麗に送れなかった点。


###次回実装したい点
-　もっと見やすく
-　URL追加
-　データフレームの画像化


もし、何か改善点があればコメントにてご教授していただけると幸いです。

###参考
スクレイピング　-　https://www.youtube.com/watch?v=LgZ8Li97yoM&list=PLavQwENTsEBWylZ9HrWXejSYs4eTjvVm7&index=11
kotlinx.datetime.Instant を Parcelable にする

## はじめに

`java.time.Instant` は Serializable ではありませんが、kotlinx.datetime パッケージにある `kotlinx.datetime.Instant` は Serializable です。逆に、`java.time.Instant` は Parcelable であるのに対して `kotlinx.datetime.Instant` は Parcelable ではありません。

これを表にすると次のようになります。

| | Serializable | Parcelizable |
|-|-|-|
| `java.time.Instant` | ✕ | ◯ |
| `kotlinx.datetime.Instant` | ◯ | ✕ |

今回は、`kotlinx.datetime.Instant` を Parcelable にするコードを紹介します。

【追記】
[こちら](https://qiita.com/penguinshunya/items/3fdc44d563e336403d7a)に `java.time.Instant` を Serializable にする方法を書きました。

## 実装

次のコードは、Nullable な Parcelable Instant を作るために必要なオブジェクトです。

```kotlin
object NullableInstantParceler : Parceler<Instant?> {
  override fun create(parcel: Parcel): Instant? {
    val str = parcel.readString() ?: return null
    return Instant.parse(str)
  }
  override fun Instant?.write(parcel: Parcel, flags: Int) {
    if (this == null) {
      parcel.writeValue(null)
    } else {
      parcel.writeString(this.toString())
    }
  }
}
```

そして、Nullable でない Parcelable Instant を作るために必要なオブジェクトは次のようになります。

```kotlin
object InstantParceler : Parceler<Instant> {
  override fun create(parcel: Parcel): Instant {
    val str = parcel.readString()
    require(str != null)
    return Instant.parse(str)
  }
  override fun Instant.write(parcel: Parcel, flags: Int) {
    parcel.writeString(this.toString())
  }
}
```

## 使用例

次のように使用します。

```kotlin
@Parcelize
data class MyData(
  val instant1: @WriteWith<InstantParceler> Instant,
  val instant2: @WriteWith<NullableInstantParceler> Instant?,
) : Parcelable
```
【Rails】N+1問題についてのまとめ

#N+1問題とは？

N+1問題とは、データベースからデータを取り出す際に、大量のSQLが発行されてパフォーマンスが低下してしまう問題のことです。

__N+1問題の具体例__

railsではallメソッドやfindメソッドを使ってデータベースからデータを取得しています。
ターミナルのログを見ると実際には下のようにその都度SQLが実行されています。

 
```SQL:SQL
Product Load (2.7ms)  SELECT `products`.* FROM `products`
```
__usersテーブル__

| id | name |
|:-:|:-:|
| 1 | 山田  | 
| 2 | 新井| 
| 3 | 田中  |
| 4 | 北川| 


__productsテーブル__

| id | product | group_id|
|:-:|:-:|:-:|
| 1 | カレー  | 2 |
| 2 | 魚  | 1 |
| 3 | 焼肉  | 3 |
| 4 | 刺身　| 1 |

「１人のuserは複数のproductsを持つ関係なので、Userモデルにhas_manyメソッドを定義し、Productモデルにはbelongs_toメソッドを定義します。

```ruby:UserモデルとProductモデルにアソシエーション定義

UserモデルとProductモデルにアソシエーション定義
# User.rb
class User < ActiveRecord::Base
    has_many :Products
end

# Product.rb
class Product < ActiveRecord::Base
    belongs_to :User
end

```

全ての所有の商品一覧」をviewで表示したい場合に、controller側で全てのuserをallメソッドで取得し、view側で飼い主の持つproductsをアソシエーションによって下記の様に記述する事が出来ます。

```ruby:N+1問題が起きてしまうコードを確認

# controller
@users = User.all

# view
@users.each do |user|
  user.products.each do |product|
    product.name
  end
end
```

「User.all」のコードが実行されると、「usersテーブルからusersテーブルの全てのカラム」が取得。
このSQLによって、usersテーブルに１回のアクセス。

次にveiw側。SQLをみると、productsテーブルに対して、4回のアクセスが行われている。

```view側:N+1問題が起きてしまうコード
@groups.each do |group|
  group.products.each do |product| 
    cat.name
  end
end

# このコードが4回のSQL文を発行
SELECT `products`.* FROM `products`  WHERE `products`.`group_id` = 1
SELECT `products`.* FROM `products`  WHERE `products`.`group_id` = 2
SELECT `products`.* FROM `products`  WHERE `products`.`group_id` = 3
SELECT `products`.* FROM `products`  WHERE `products`.`group_id` = 4
```

eachメソッドで@groupsが持つusersテーブルから全てのレコードを一つずつgroupに入れている。

SQLが「usersテーブルへのアクセスが１回 」に対して「productsテーブルへのアクセスがgroupsテーブルのレコードの数(4回)」発行

__このようにアクセス１回に対して、関連するテーブルがN回発行されている1+Nの状況を「N+1問題」と言う。__

。

#N+1問題の対処法

__includesメソッド__

```ruby:includesメソッド
includesメソッドの使用例 -->
@users = User.includes(:user)
```

```
@users = User.allで取得していた箇所を@users = User.includes(:products)に変更します
```

```controller側:includesメソッド
@users = User.includes(:products) # User.allから変更

 # 発行される2つのSQL
SELECT `users`.* FROM `users` 
SELECT `products`.* FROM `products`  WHERE `products`.`group_id` IN (1, 2, 3, 4)
```

２つのSQLが発行されました。1行目は、usersテーブルの全てのレコードを取得するSQL文です。
2行目は、productsテーブルからWHERE句で指定した条件にマッチするレコードを取得しています。

#まとめ
includesメソッドを使わない場合は、関連するuser_idカラムの値を１つずつ指定して取得していたのでproductsテーブルに4回のアクセスが必要でしたが、IN句でカラムの値をまとめて指定した事によって１回で取得出来るようになりました。includesメソッドを使ってレコードをまとめて取得させる事によって必要以上のSQLを発行する事なく済み,パフォーマンス向上に繋がる:blush:
AtCoderをするなら知っておきたいSTLデータ構造(Standard Template Library)

# 筆者
水色

using namespace std;

# TL;DR
- vector
- set
- map
- multiset
- unordered_map
- queue
- deque
- priority_queue
- stack

## vector
可変長配列

**できること**
 indexで要素アクセス $O(1)$ 
 末尾への挿入 $O(1)$

## set
順序つき集合
平衡2分木による実装
**できること**
to be continued ...

## map
連想配列

# 参考
[cpprefjp - C++日本語リファレンス](https://cpprefjp.github.io/)
Laravel 8 の php artisan down では --allow ではなく --secret を使う

Laravel 8 で `php artisan down --allow={俺のIP}` って打ったら「`--allow` なんかねぇ！」って言われたんですが本番環境だったので泣いてしまいました。これに関して日本語の記事が皆無だったのでメモ。

# Laravel 7 まで
メンテナンスモードにするには `php artisan down` だが、これでは開発者が何かテストしたい場合にもアクセスできず門前払いになってしまう。そこで、`--allow` オプションでIPを指定することにより回避することができた。

```
$ php artisan down --allow=127.0.0.1
```

# Laravel 8 では
`--allow` は消えました。でももっと楽です。

### `--secret` オプション
これを利用して、落とすときにパスワードを設定しておく。

```
$ php artisan down --secret="hogehoge"
```

その後、`https://[ドメイン]/hogehoge` にアクセスする。すると `/` にリダイレクトされると同時にメンテナンスモードが解除される。

内部的には、`https://[ドメイン]/hogehoge` に行った時点でクッキーが保存されて、そのキーによって認証されてる感じらしい。

言うまでもないが、これを使えばいちいちIPを気にする必要もないし複数人での確認も楽勝となる。めっちゃいい機能だけどマジで焦ったんだからね！

### 参考
https://www.amitmerchant.com/access-application-in-maintenance-mode-using-secret-token-in-laravel-8/
【Git】GitHubを利用した開発の流れ ~GitHub Flow~

##プルリクエストの流れ
プルリクエストは、自分の変更したコードをリポジトリに取り込んでもらえるよう依頼する機能。

###プルリクエストの手順
１. リモートのmasterブランチをpullして、ローカルのmasterブランチを最新の状態にする。

```
$ git pull origin master
```

２. 自分の開発を行うためのブランチを作成し、自由にファイルを編集する。

```
//例
$ git checkout -b 'pull_request'
``` 

３. ファイルを編集したらコミットを行い、リモートへも新しいブランチ名でpushする。

```
$ git add .
$ git commit
$ git push origin pull_request
```

４. GitHubでPull requestを作成する。

* GitHubのリモートリポジトリのページを開く。
* Pull requestのタブの「New pull request」ボタンをクリック。
* baseは元々の基盤となるこれからpull requestする先のブランチ（master）、compareはこれからpull requestを行うブランチ（手順３. でpushしたpull_request）を選択する。
* writeのタブにコメントを入力する。（例：レビューお願いします。）
* 「Create pull request」ボタンをクリック。
* 「Reviewer」をクリックし、コードレビューを依頼する人を選択する。（レビュアーにはプッシュ通知が届く。）
* レビュアーは、Pull requestのタブ内からプルリクエストを選択し、Files changedのタブからレビューコメントや修正点を書く。
* レビュアーがレビューを行うとプルリクエストした人へ通知が届くので、レビューが通るまで修正を繰り返す。
* レビュアーが、Pull requestタブのReview changesよりApproveを選ぶ。
* （コンフリクトが起きている場合は）コンフリクトを解消し、ローカルからコミット、リモートへpushし直す。
* Pull requestタブより「Merge pull request」ボタンを押すと、マージされる。
* プルリクエストを行ったブランチはもう不要なので、「Delete」ボタンで削除する。


##GitHub Flowの流れ
１. ローカルのmasterブランチから、作業用のブランチを作成する。
２. 作業用のブランチにおいて、ファイルを編集し、コミットを行う。
３. 作業用ブランチと同名のブランチをGitHubへpushする。
４. GitHubでプルリクエストを作成する。
５. コードレビューを行い、リモートのmasterブランチにマージする。
６. 本番サーバーへ、リモートのmasterブランチをデプロイする。（masterブランチは、常にデプロイできる状態に保つ。）
Irisデータ処理（機械学習：前処理編）

##機械学習の全体の流れ
➀データの取得
➁データの加工(標準化、テスト用データと学習用データの分割など）
➂モデルの定義を行い、データを入力する。
➃機械学習を行う。（順伝播と逆伝播を繰り返し、精度を上げていく）
➄機械学習の結果を評価する。問題があれば、チューニングを行う。

今回は前処理に分類される➀と➁について整理したい。

##今回使用したPythonテクニック
➀One-Hot表記
➁内包表記
➂スライス
➃行列の初期化(onesとzeros）
➄assert(検証)

##ソース

・モジュールの導入

```Python
#sklearnモジュールの呼び出し
from sklearn import datasets
import numpy as np
```

・データの読み込み

```Python
#データの読み込み
iris_data=datasets.load_iris()
#データについて、測定値（4種類）とそれに対するラベルについて取得する。
input_data=iris_data.data 
correct_data=iris_data.target 
```

・データの中身の確認

```Python
print(input_data) #左側から「sepal lengh」「sepal width」「petal length」「petal width」
　　　　　　　　　　#sepal⇒がくpetal⇒花弁
>>>
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
・・・
 [6.5 3.  5.2 2. ]
 [6.2 3.4 5.4 2.3]
 [5.9 3.  5.1 1.8]]

print(correct_data) #0⇒setosa 1⇒vesicolor 2⇒versinica
>>>
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 ・・・ 2 2 2 2 2]

#データ数の確認
len(input_data)
>>>150

#input_dataとcorrect_dataの個数が等しいかを確認
assert len(input_data) == len(correct_data)
>>>True
```

・データの標準化

```Python
#データの平均値の取得
average=np.average(input_data,axis=0)
#データの標準偏差の取得
std=np.std(input_data,axis=0)
#データの標準化(標準値の平均値は0で、標準偏差は１になる)
data=(input_data-average)/std #input_dataは行列だが、averageとstdはベクトルである。⇒ブロードキャストの使用
```

・平均値、標準偏差、標準値の確認

```Python
#四つのデータごとにデータが算出されていることが確認できる。
print("平均値: {}".format(average))
print("標準偏差: {}".format(std))
print("標準値: {}".format(data))
>>>
平均値: [5.84333333 3.05733333 3.758      1.19933333]
標準偏差: [0.82530129 0.43441097 1.75940407 0.75969263]
標準値: [[-9.00681170e-01  1.01900435e+00 -1.34022653e+00 -1.31544430e+00]
・・・ [ 6.86617933e-02 -1.31979479e-01  7.62758269e-01  7.90670654e-01]]
```

・ラベルデータのOne-hot化

```Python
#ラベル配列の長さの取得
correct_data_length=len(correct_data)
#ラベルについてOne-hotで表現する。
correct=np.zeros((correct_data_length,3))
for i in range(correct_data_length):
  correct[i,correct_data[i]]=1.0　#四つのデータごとに、どのラベルに属するか(属するものに対して１と表現する。それ以外は0とする)
```

・One-hot化したラベルデータの中身の確認

```Python
print(correct)#左から順にsetosa,vesicolor,versinica
>>>
[[1. 0. 0.]
 [1. 0. 0.]
 [1. 0. 0.]
 [1. 0. 0.]
 [1. 0. 0.]
・・・
 [0. 0. 1.]
 [0. 0. 1.]
 [0. 0. 1.]]
```

・入力データについて、学習用とテスト用に分割する。

```Python
#indexリストの準備
index=np.arange(correct_data_length)
#入力データ(input_data)のindexについて、奇数と偶数ごとに振り分ける
#[]の中に条件を書く方法は内包表記である。
index_train=index[index%2==0] #偶数行について学習用データとする。
index_test=index[index%2!=0] #奇数行についてテスト用データとする。

#行列のスライスを用いて、実際に学習用とテスト用に分割している。
input_train=input_data[index_train,:]
corrext_train=correct[index_train,:]
input_test=input_data[index_test,:]
corrext_test=correct[index_test,:]
```

##補足

・スライス

```Python
#一次元配列のスライス（ただし、先頭のインデックスは0であることに注意する。）
a=np.array([1,4,5,7,3,9,8])
print(a[1:4]) 
>>>[4 5 7]

#ステップ数2でインデックス1～4の範囲でスライスする。
print(a[1:4:2])
>>>
[4 7]

#二次元配列のスライス
b=np.array([[0,2,4],
            [3,5,9],
            [4,7,8]])
print(b[0,:])#0行のデータをすべて取得する
print(b[:,0])#0列のデータをすべて取得する
>>>
[0 2 4]
[0 3 4]
```

#参考文献
・はじめてのディープラーニング
【Vue.js with TypeScript】propsでObjectを渡すときの型の指定方法

## 概要
propsで親componentから子componentにObjectを渡すときの型を、interfaceで指定する方法。

## 方法
`type: Object as () => SampleType,` のようにinterfaceを返すメソッドを指定する。

## 実装例

```vue
<template>
  <div id="sample-button">
    <button class="m-3 btn btn-sm btn-primary" @click="clickChildComponent">
      SampleButton
    </button>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import SampleType from "@/types/SampleType";

export default Vue.extend({
  name: "sample",
  props: {
    sample: {
      // SampleTypeというinterfaceをメソッドにして指定する
      type: Object as () => SampleType,
      required: true,
    }
  },
  methods: {
    clickChildComponent(): void {
      console.log(this.sample);
    }
  },
});
</script>
```

## 参考
- [Using a Typescript interface or type as a prop type in VueJS](https://frontendsociety.com/using-a-typescript-interfaces-and-types-as-a-prop-type-in-vuejs-508ab3f83480)
- [Vue.jsでObject型のPropsにTypeScriptの型を割り当てる
](https://count0.org/2019/03/01/object-type-on-vue-props.html)
【PHP】三項演算子の結果を文字列結合したいが上手くいかない

PHPで、三項演算子の結果を文字列結合して表示したいことがあり、次のようにコードを書いてみて『結果：Ok』を期待したけれど、実際に出力されるのは『Ok』のみ。
「結果：」の形跡はまったくなく不思議。いったいどこにいってしまったのだろうか。

```PHP
$hoge = 3;
echo '結果：'. ($hoge == 3) ? 'Ok' : 'Ng';
＞Ok
```
# とりあえずググってみた
「teratail」で質問と回答を見つけた。

https://teratail.com/questions/3894

>(’答えは’.0) ? '正解！' : '間違い！';
>('答えは、0’) ? '正解！' : '間違い！';
>(TRUE) ? ' 正解！' : '間違い！';
>
>
>なので、三項演算子の部分を()で囲みましょう。

「三項演算子の部分を()で囲み」で解決なのだけれど、少し丁寧に理解しておこうと思う。

# 1つ1つ動きをみていく
読み解くには「演算子の優先順位」が分かればOKです。

https://www.php.net/manual/ja/language.operators.precedence.php

```PHP
echo '結果：'. ($hoge == 3) ? 'Ok' : 'Ng';
```

この文の演算子は、3つ

| 演算子 | 名前 |
|:-:|:-|
| . |文字列演算子|
| == |比較演算子|
| ? :   |三項演算子|

優先順位は、上から順に、``.`` > ``==`` > ``? :`` となる。

でも括弧で囲われているところが一番最初に評価される。
``($hoge == 3)`` は、true だ。

```PHP
echo '結果：'.true ? 'Ok' : 'Ng';
```

でお次は、三項演算子より文字列演算子の方が、優先順位の高いので、``'結果：'.true`` の文字列結合が行われる。
true の型変換が起こって、``'結果：1'`` になるのかな。

```PHP
echo '結果：1' ? 'Ok' : 'Ng';
```

そして最後に三項演算子が評価され、文字列の ``結果：1`` は、true と判断されるので前に書いた式が、echo される。

```PHP
echo 'Ok';
＞'Ok'
```

一見「何が起こったんだ！」と慌ててしまったけれども、しごく仕様通りの動きだったことが分かる。前の文字列と参考演算子の条件の結果が結合されてしまっていたんですね...

蛇足だけれど、今回のケースでは、以下のように三項演算子の部分を括弧で囲んでしまえばOK。
これで、最初に三項演算子が評価されるので、期待通りに出力されます。

```PHP
$hoge = 3;
echo '結果：'. (($hoge == 3) ? 'Ok' : 'Ng');
＞'結果：Ok'
```
「成長」を加速させる心構え

「成長」を加速させる心構え。とあるネット記事で誰にでもできそうな有益な方法だなと共感できる記事を見つけた。
若い人も、ベテランも、エンジニアも、そうでない人も、組織の中で働くうえで、自分が「成長」できる環境に身を置けるメソッド－

その記事の内容が、「言葉」ではなく「心」で理解できた！
そう感じたので、皆にも紹介したいと思った。

組織の中で自分の立ち位置を悩んでいる、あるいは、自分の仕事に自信が持てないと感じている人たちに是非読んでもらいたい。

それは、組織の中で「最後の砦」を目指す、「ラストマン戦略」 。
現、クレディセゾンCTOである、小野和俊さんの記事だ。

実際の記事がコレ。詳しくは記事を参照されたい。

https://type.jp/et/feature/14193/


##組織の中で”最後の砦”を目指す「ラストマン戦略」

記事にはこう書いてある。小野さんの書籍『その仕事、全部やめてみよう』(ダイヤモンド社)で紹介されているという。

>ラストマン戦略とは、組織の中で自分が一番詳しくなれそうな領域を決め、「あの人が分からないなら、他の誰も分からないよね」と言われるような、最後の砦とも言うべきスペシャリストを目指す成長戦略だ。

本は読んでいないがピンときた。
組織＝自分のチームの先輩や同僚たちに勝てそうな「領域」。
自分が一番得意だ。一番になれると思う「領域」。先ずそれを見つけ出す。
誰にだって何か一つは自分が得意だと思っていることがあるはずだ。「好き」なことでもよい。
それを見つけ、磨くのだ。こっそりではダメだ。実践の中で、組織の中で、積極的に。

若手だったり、これまでと違った職種のチームに入ると遠慮や不安が当然あるだろう。
「早くチームの戦力にならなければ！」とか、「チームのシゴトを覚えなければ」などの考えは当然だ。
だが、しかし。それだけでは「成長」は加速しない。いや、その気持ちがあれば、確実に「成長」はしていくのだろうが、それは周りの上司・仲間から見て「想定内」の成長に留まっているレベルで終わるのかもしれない。
本人は一生懸命に努力しているのにも係わらず、だ。

##「私が一番得意だ。私に任せろ」の存在を目指す。

小野さんは記事で語る。「あの人が分からないなら、他の誰も分からないよね」と言われるような、最後の砦とも言うべきスペシャリストを目指す。
最初からそんな「武器」があるなら苦労しない。
だから「見つける」のだ。「組織の中で一番詳しくなりそうな領域を決め」て。
それは、先ず自分が「好きなこと」、「これまで続けられてきたこと」であるはずだ。
それは、「これからも継続して続けられること」「伸ばしていける」と自分の中でちょっとは自信が持てることであるはずだ。
そして、その中で「チームの中で、一番になれそうだ」とおもう領域。それは何か？
最悪、今はビリでもいい。上司や先輩に褒められたことでもいい。周りの人が誰もやってなさそうなことでもいい。
自分にとって、それに「情熱」を持つことが出来て、いつの日にか「チームで一番になってやるぞ」、控えめに言って「チームで一番になれるかもしれない」といったことを見つけてみよう。

それは、どんな些細なことでもいい。議事録を書くが早い、上手い。プレゼン資料を綺麗にわかりやすくまとめることが出来る。人の話を聴くことが得意。褒め上手。調査してレポートにまとめるのが得意。エクセルの機能のことなら誰よりも詳しい。今の仕事と直結しないけど、〇〇のことなら一番詳しい自負がある。

それを見つけられたら、認識できたら、組織の中で徹底的にアピールしよう。腕を磨こう。そして周りに認めてもらおう。

そうすることで、その領域で自分自身がプライドを持って「成長」することが出来るし、組織からも頼られる。頼られるということは、「成長」の機会が与えられるということ。
組織に頼れられることで、その「領域」以外の業務における別の領域の「成長」機会も手に入れることが出来るだろう。


##『やりたいこと』をとことんやって突き抜けることが近道
小野さんもこの記事で書いていました。この言葉たちにも非常に共感が持てる。私の社会人人生においても。もっと早く出会いたかったくらいだ。まだまだ私も遅くないと思っているけど。


>「若手エンジニアが掲げる目標として、『先輩の役に立ちたい』は少々謙虚過ぎる。組織の中でラストマンになるぐらい高い目標を目指した方が、本人にとってもチームにとっても良い結果を招きます」

>「社会人になると、自分の興味をとことん伸ばすことよりも、自分のできていない部分をカバーすることばかりやってしまうんですよね。要は『しなければならない』という考えで全ての仕事をしてしまう状態です。それでみんなつまらなくなってしまう。

>一見いまの仕事に直結しなくても、自分が興味をもって突き詰めたことが、いつどこで、何につながるか分かりません

若手だからって、仕事だからって、与えられた業務をこなすだけって勿体ないと思います。
そりゃ、仕事だから、与えられた業務は大事。ミッションです。
でも、それだけじゃあつまんないし、「真」の成長は望めない。
自分自身が、「情熱」を持って「好きなこと・一番になれそうなこと」を見つけて、徹底的にアピって極める。
そこはブレーキをかけずに積極的でいいんだと思います。
大丈夫。突っ走り過ぎたら、上司や仲間が注意してくれますよ。
【爆速レビュー】データサイエンティスト検定受験期

# はじめに

2021年9月12日（日）に、データサイエンティスト検定を受験しました。この検定は、2021年9月11日（土）から新たに始まった試験です。本記事ではそのデータサイエンティスト検定の概要と、私が実際に受験して感じたことを主に書いていきたいと思います。

# データサイエンティスト検定とは

> 『データサイエンティスト検定™ リテラシーレベル』（略称：DS検定™ ★）とは、アシスタント・データサイエンティスト（見習いレベル：★）と数理・データサイエンス教育強化拠点コンソーシアムが公開している数理・データサイエンス・AI（リテラシーレベル）におけるモデルカリキュラムを総合し、実務能力と知識を有することを証明する試験です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652854/d6d8f13b-96a4-8538-a772-5188c357c532.png)

参考：https://www.datascientist.or.jp/dskentei/

# 検定概要
> - 受験資格	なし
- 実施概要	選択式問題
- 全国の試験会場で開催(CBT)
- 問題数80問程度
- 試験時間90分
- 出題範囲	スキルチェックリストの3カテゴリ（データサイエンス力、データエンジニアリング力、ビジネス力）の★１（見習いレベル）相当と数理・データサイエンス・AI（リテラシーレベル）におけるモデルカリキュラムを総合した範囲

参考：https://www.datascientist.or.jp/dskentei/
※なお今期の受験申し込みは既に終了しています。

# 検定の対象
> 本検定の受験対象者は以下のような方を想定しています。
・データサイエンティスト初学者
・これからデータサイエンティストを目指すビジネスパーソン
・データサイエンティストに興味を持つ大学生や専門学校生など

参考：https://www.datascientist.or.jp/dskentei/

公式ページに記載の検定の対象者から分かるように、比較的経験が浅いデータサイエンティスト見習いのような方や、実務経験はないものの、データサイエンスに興味を持っている方向けの検定です。私自身、データサイエンスの分野に携わり始めて１年と数か月ですので、上記に該当する一人だと思い、受験することにしました。

# 私のバックグラウンド
- 業務：データ分析、社内DX推進など
- 学生時代の専門分野：生体医工学（脳波の研究など）
- データサイエンス周りの保有資格：統計検定3級・2級、基本情報技術者、Dataiku Core Designer

# 受験に受けた準備
恥ずかしながら、この試験に向けた対策は全くしないまま受験に挑む形となりました。
[公式テキスト](https://gihyo.jp/book/2021/978-4-297-12261-4)や[対策講座](https://www.skillupai.com/ds/)はあるのですが、それらの学習に十分な時間をかけられなさそうであったため、開き直って、いっそこのまま受験してみたほうが現在の力量がわかるのでは？といった考えに至りました。

やったことといえば、先述の検定概要で試験時間と大体の出題内容のチェック、受験会場の確認程度です。

# 試験の概要
## 受験会場到着～試験終了まで
試験の流れは下記のような感じです。

1. 受験会場で予約の確認
2. 座席でIDとパスワードを確認して試験の画面にログイン
3. 操作方法のチュートリアル実施（ほかのCBT試験と比較して特殊なことは特になし。しいて言うなら画面に「電卓」があるので、その使い方くらい？筆者は使わなかったのでわかりません泣）
4. 本試験開始
5. （回答を終えたら）画面の指示に従い、結果レポートを印刷し、試験官の方の案内に従って終了

## 試験の内容について
基本的に[こちらのページ](https://www.datascientist.or.jp/dskentei/)の **データサイエンティスト検定™の試験範囲** に記載のある内容に沿っていたと思います。
強いて言うなら、やや時事問題に近いような問題がありました。ただ、これも知っていれば解くことのできる内容だと思います。

概要では、問題数80問程度とのことでしたが、実際の問題数は90問で、（記憶が正しければ）すべて4択の選択問題でした。
試験時間は90分でしたが、私の場合、（見直し含め）60分程度で解き終わり、試験を終了しました。

# 試験を終えての感想
全く対策なく挑んだ本試験でしたが、結論から言うと、そのスタンスである程度通用してしまいました。その要因は下記のようなところにあると思います。
- 国語の問題かな?と思うような問題の出題が一定数あった。
- ほかの資格試験の内容と被る部分が多くあった。（統計検定はもちろん、基本情報技術者試験、G検定の内容も。）
- そもそもデータ分析したことがない人でも常識で選べそうな問題もそこそこあった。

偉そうなこと言っていますが、実際のスコアはこんな感じなので、めちゃめちゃ高得点というわけでもないです。
![scan-001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/652854/448546ed-cf09-ede5-6dd3-c72f6f70fcd1.jpeg)

結果レポートに記載の通り、スコアは出ていますが、合否はまだ不明です。（合格していると信じていますが）まだ不合格の可能性も残っています。

# 試験までにやっておいたほうがよさそうなこと
統計検定や基本情報技術者試験、G検定の内容が身についている人ならば、特別な対策は不要かと思います。
しいて言うなら、[模擬問題](https://www.datascientist.or.jp/common/docs/practice_v1.1.pdf)くらいは目を通しておいたほうが良いかも？

初学者の方は、先日の公式テキストや対策講座に取り組むのが良いと思います。
統計、機械学習、情報リテラシーとやや広めの範囲から浅めの内容が出題されました。専門書でがっつりやるよりも試験に特化したコンテンツに取り組むほうが効率が良い気がします。

あと、事前知識の有無にかかわらず、情報リテラシーに関する時事的なことはどこかで確認しておくとよいと思います。このあたりの知識を問う問題が数問出題されました。

# 終わりに
データサイエンティスト検定の情報は、まだあまり出回っていないと思い、本記事を作成しました。
本記事が、今後受験される方の参考になれば幸いです。
【LWC】datatableでrowActionを使用する

#はじめに
今回はdatatableのrowActionについて書きます。rowActionとは標準のリストビューの「編集、削除、所有者の変更」の３つのアクションが表示されるメニューのことです。datatableではカスタムで様々なアクションを作成することが出来ます。
#actionを定義
まずrowActionとして表示するactionを定義します。今回は詳細画面へのリンクと削除です。

```javascript
const actions = [
  {label: 'Details', name: 'details'},
  {label: 'Delete', name: 'delete'},
];
```
#datatableのcolumnsにtype='actionを追加
定義したアクションを他のカラムと同様にcolumnsに定義します。

```javascript
const columns = [
    { label: '商談名', fieldName: 'Name'},
    { label: '金額', fieldName: 'Amount', type: 'currency'},
    { label: 'フェーズ', fieldName: 'StageName', type: 'text', editable: true},
    // 定義したAction
    { type: 'action', typeAttributes: {rowActions: actions, menuAlignment: 'right'}},
];
```
#HTMLにonrowaction属性を追加
actionの定義が出来たらhtml側にonrowaction属性を追加します。

```html:opportunityTable
<template>
    <div>
        <lightning-datatable
            key-field="id"
            data={records}
            columns={columns}
            hide-checkbox-column="true"
            show-row-number-column="true"
            onrowaction={handleRowAction}>
        </lightning-datatable>
    </div>
</template> 
```
あとは個々のactionに対する処理を書いていけば完成です。今回は詳細ページへの遷移しか処理を書いてませんが、参考までに載せておきます。

```javascript:opprotunityTable.js
import { LightningElement, wire, api } from 'lwc';
import getOppTable from '@salesforce/apex/OpportunityTableController.getOppTable';
import { NavigationMixin } from 'lightning/navigation';

const actions = [
  {label: 'Details', name: 'details'},
  {label: 'Delete', name: 'delete'},
];

const columns = [
    { label: '商談名', fieldName: 'Name'},
    { label: '金額', fieldName: 'Amount', type: 'currency'},
    { label: 'フェーズ', fieldName: 'StageName', type: 'text', editable: true},
    { type: 'action', typeAttributes: {rowActions: actions, menuAlignment: 'right'}},
];

export default class OpportunityTable extends NavigationMixin(LightningElement) {

  columns = columns;
  records;
  @api recordId;

  @wire(getOppTable, {accId: '$recordId'})
  wiredOpps({error, data}) {
    if(data) {
      this.records = data;
    }
  }

  handleRowAction(event) {
    console.log('■' + event.detail.action.name);
    let actionName = event.detail.action.name;
    let row = event.detail.row;
    switch(actionName) {
      case 'details':
        // navigate to record detail page
        this[NavigationMixin.Navigate]({
          type: 'standard__recordPage',
          attributes: {
            recordId: row.Id,
            actionName: 'view'
          }
        });
        break;
      case 'delete':
        alert('delete but not really');
        break;
    }
  }
}
```
標準では出来ないようなアクションも定義できると思うので使い道は多いのではないでしょうか。
【Unity】Unity始めてみた（インストール編）

# Unityって？
- Unity Technologieが開発・販売しているゲームエンジン
- 2005年に誕生
- ゲーム開発では世界シェアナンバー1を誇る

## できること・用途
- **ゲーム開発**

『ポケモンGO』、『どうぶつの森ポケットキャンプ』、『スーパーマリオラン』、『白猫プロジェクト』といった、あまりゲームに詳しくない自分でも知っているような有名ゲームも、Unityを使って開発されている。

- **医療業界**、**建築業会**、**自動車業界**

各種シミュレーション開発に使用されるなど、ゲーム開発以外の用途でも使用が広がっている。
Unityは標準機能として3Dオブジェクトを操作するためのライブラリを備えており、ライブラリを使用することでVR/ARのように現実と仮想空間の要素を併せ持つ表現が容易に実装可能であることが要因。

## 特徴
**・ノンプログラミングで制作可能**
簡単な制作であればプログラミングを行う必要が無い。
『Unity Script』と呼ばれる拡張機能を使用することで、C#・Javascriptによる複雑な拡張処理の実装も可能。

**・2D、3Dの両方に対応**
新しいプロジェクトを作成する際に選択した2D/3Dのモード設定にかかわらず、いつでもエディター上で設定を簡単に切り替えられる。

**・クロスプラットフォーム対応**
Andoroid、iOS、Linux、Windows、Xboxなどに対応しており、これら複数の異なるプラットフォームで同一のコンテンツを提供することが可能。

# Unityのインストール
## 1. Unity ID アカウントを作成する
![スクリーンショット 2021-09-12 19.20.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/e0615e2c-2a25-9515-b098-b80d35ab37f8.png)
Unityの公式サイトで、『Create a Unity ID』をクリック。
メールアドレス、パスワード、ユーザーネームなどを設定し、メールアドレスに届く認証リンクをクリックすればアカウントの作成完了。

## 2. 利用プランを選択する
『Get started』をクリックし、利用プラン選択画面へ。
個人開発用の無料プランがあるので、それを選択。
![スクリーンショット 2021-09-12 19.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/d1112e30-d5eb-1afb-6b8e-694330bcbbfd.png)

## 3. 手順に沿ってダウンロード・インストールする
ダウンロードには10分程度かかったが、これだけでインストール完了。簡単…！
![スクリーンショット 2021-09-12 19.33.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379501/87f95451-2c6a-bcf0-8657-6e6c602bca31.png)
OpusのフォーマットとOggのコンテナ

# はじめに
Opusそのものについては, 別に記事があるのでそちらに譲ります.
[音楽ファイルが96kbpsになる日――Opus音声コーデックの実力](https://qiita.com/keiya/items/7d14adff689207a63b4b)

ソフトウェアで扱う場合は, 公式[Opus Codec](https://opus-codec.org/)のライブラリを使用することが普通と思います. コーデックライブラリ`libopus`では少し扱い辛いため, Oggコンテナをとおして読み書きしやすくした `opusfile` とともに使うと楽です.

大した理由はないのですが, Oggコンテナを使わない方法を考えてみます.

## 音質について
技術的に, 汎用とスピーチ向けの圧縮技術を用いています. そのせいか最大ビットレートを下げていった場合に, 大きく音質が切り替わる点があります. また, Vorbis等に比べ可聴域の範囲で高音域が残りやすいように感じます. スピーチでは, 母音が残っていればそれなりに聞き取れるからだと思っています.

# Opusのエンコーダ・デコーダ
[Opus documentation](https://opus-codec.org/docs/)にAPIのドキュメントがあります. 重要なのは, 処理はサイズが決まったフレーム単位で行うことです. Wavのように全ての圧縮データをひとつなぎにしてしまうと, デコード時にフレームの切れ目がわからなくなりうまく処理できません.

# Oggコンテナ
コンテナの仕様は, [RFC3533 - The Ogg Excapsulation Format Version 0](https://datatracker.ietf.org/doc/html/rfc3533)になります. Oggコンテナではページ単位でデータの塊を管理し, 同じストリームIDのページ群が仮想ストリームを作ります. 次はRFC3533からの引用ですが, これは２つのルールを表現しています. 仮想ストリームの始まり（bos）は, 全仮想ストリームで連続していなければならない. 全ての仮想ストリームの終了（eos）が出現するまで, 次の仮想ストリームの始まりが出現してはならない, というルールです.

```
RFC3533
-------------------------------------------------------------
|*A*|*B*|*C*|A|A|C|B|A|B|#A#|C|...|B|C|#B#|#C#|*D*|D|...|#D#|
-------------------------------------------------------------
bos bos bos             eos           eos eos bos       eos
```

# Ogg-Opus
[RFC7845 - Ogg Encapsulation for the Opus Audio Codec](https://datatracker.ietf.org/doc/html/rfc7845)に仕様があります. Opus自体は最大２チャンネルまでの圧縮しかできませんが, Oggの仮想ストリームを利用して256チャンネルまで対応できるように設計されています. フレームの切れ目問題もページの単位を利用すれば解決できます.

# まとめ
役に立たない知識ですが, ミドルウェアに頼れない状況で, できるだけ低遅延・高品質に音を再生したい場合に必要になるかもしれません.
サーバーレスについて

#○はじめに
AWSの学習の際に、サーバーレスってなんぞ？ってなったので今回、サーバーレスについて調べてみました。

・サーバーがなくても動くということ？

→そうではないみたいです。

どういうことなのか、記載していきます。

#○サーバーレスとは？

>サーバーレスとは、サーバーの構築や保守などの面倒な管理、付加対策などをすることなく、サーバー上でプログラムを実行できる仕組みです。

>プログラムさえ作成すれば、すぐにサーバーで実行できる。

>https://blog.qbist.co.jp/?p=2654

つまり、

**本来必要な、サーバーのことを考えなくてもいい**

ということ。

楽に、運用〜保守ができることは分かったが、具体的に、どんなことができるのでしょうか？

## サーバーレスを使用するメリット

###●サーバーの管理を考える必要が無い

###●効率的にサーバーを運用できる

システムは基本的には、24時間365日稼働しています。
しかし、中には常にサーバーを動かし続ける必要のないサービスも存在します。
例えば、
・１日に1度だけメール送信を行う仕組み
・ビックデータの分析（短時間で大量のデータを集める）

このようなサービスは、常に稼働しているサーバーでは余分なコストがかかってしまう。

そのため、サーバーレスメリットがあります。
[VSCode] WSL2を使わず、Remote containerを使う方法

ポイントだけ書きます。

# サーバ側

- アカウント作成。PCからSSHログインできるようにする
- dockerを動作するようにする
- samba serverのcontinerを起動

USERID、GROUPIDは、作成したアカウントのUID,GIDにあわせる。

```bash
sudo docker run -it -e USERID=1000 -e GROUPID=1000 \
            -p 139:139 -p 445:445 \
            -v /home/usesrname:/share \
            -d dperson/samba -p \
            -u "username;password" \
            -s "share;/share;yes;no;no;username" 

```

# PC側

- VSCODEにRemote-conainer プラグインをインストール
- Docker Disktopをインストール
- docker context でサーバのdockerにつながるようにする
- sambaで公開したフォルダをz:\ドライブマウント
- vscode-remote-try-nodeをz:にgit clone
- cloneしたフォルダをVSCODEで開く
- devcontainer.jsonに次の記述を追加

```
	"workspaceFolder": "/workspace",
	"workspaceMount": "source=/home/masa/vscode-remote-try-node,target=/workspace,type=bind,consistency=cached"
```
- コマンドパレットで　Open Folder in Containerを実行


# 参考資料

https://code.visualstudio.com/docs/remote/containers-advanced#_developing-inside-a-container-on-a-remote-docker-host
【Rails】Sprockets::DoubleLinkErrorを解消する

### 1.背景
Ruby on Railsを使用して共同開発を行っています。
他の方の実装分を追加後、`rails s`でサーバーを起動すると表題のエラーが表示されました。

今回はエラー解消の手順と原因を備忘録としてまとめます。

### 2.環境
- mac.os バージョン10.15.6
- Ruby 2.7.3
- Rails 6.1.3.1
- psql (PostgreSQL) 12.6

### 3.該当のエラーと原因
今回のエラーは下記です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689555/61fa406d-2e5c-580b-baf8-56c1f9fb7485.png" width=80%>

```ruby
ActionView::Template::Error (Multiple files with the same output path cannot be linked ("top.css")
In "/Users/hogehoge/rails/team_project/app/assets/config/manifest.js" these files were linked:
  - /Users/hogehoge/rails/team_project/app/assets/stylesheets/top.css
  - /Users/hogehoge/rails/team_project/app/assets/stylesheets/top.scss
):
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689555/4591aea2-9782-75ea-13de-d776106ba393.png" width=40%>

エラーの原因は

- cssとscssが干渉している
- 拡張機能「Live Sass Compiler」が起動していた

この2点でした。
scssは別の方が実際に実装されたファイルです。
拡張機能が加わり、自動で「top.css」と「top.css.map」が作成された結果、干渉してエラーが発生していました。

### 4.解消方法

解消方法としては単純でした。今回の場合だと、
「top.css」と「top.css.map」の2つを削除するとエラーが解消され、サーバーの起動が実行されました。

### 5.拡張機能「Live Sass Compiler」について
Live Sass CompilerはVS Codeの拡張機能の一つで、Sass(Scss)を自動でコンパイルしてCSSに変換します。
拡張機能を使用するには、2つの方法があります。
（１）コマンドで下記を入力する

```Ruby
Live Sass: Compile Sass 
```
(2)VSCodeのステータスバーにある`Watch Sass`をクリックする
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689555/a2e268cc-73d9-377f-4f7e-ea9bc7ba4548.png" width=100%>

今回の場合、`Watch Sass`をクリックすることで自動でコンパイルされていました。
(気づかないうちにクリックしていたようです...)

### 6.参考
1.[Sprockets::DoubleLinkError を解消した方法](https://qiita.com/Hayato_prolife/items/0e157f606287f0729b2e)
2.[VSCodeでSass(Scss)を自動コンパイルする簡単な設定方法](https://rico-notes.com/programming/css/vscode%E3%81%A7sassscss%E3%82%92%E8%87%AA%E5%8B%95%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%99%E3%82%8B%E7%B0%A1%E5%8D%98%E3%81%AA%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95)
3.[Visual Studio Code で Sass をコンパイルする Live Sass Compiler
](https://www.bnote.net/front-end/vscode_live_sass_compiler.html)

### 7.最後に
記事の感想や意見、ご指摘等あれば伝えていただけるとありがたいです。
読んでいただき、ありがとうございました。
[Xcode] iosアプリ開発で通知が表示されない

## どゆこと

ionic + angularでiosアプリ開発を少し勉強していたところ，通知がどうやっても表示されない問題に遭遇しました．


初めはコードに問題があると思い，色々と調査を行いましたがどうやら原因はそうではなかったようです．


iosアプリはApple IDがあれば無料で開発することができますが，有料のApple Developer Program(ADP)というメンバシップが存在し，その有料のメンバシップに入っている開発者でないと使えない機能が存在するようです．


今回私が詰まっていた通知機能は有料会員でないと使えない機能でした．

なので有料会員にならないと試せないようです．

有料会員でないと使えない機能及び無料会員でも使える機能は以下のページにまとまっています．

https://help.apple.com/developer-account/#/dev21218dfd6

![参考](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401124/b462e83d-52a7-c035-0cc8-94b50d4f92e4.png)

有料デベロッパーと無料デベロッパーでは使える機能の数に大きな差がありますね．


## あとがき


コンソールには通知のログが出てるのにどうしてもアプリの画面には通知が表示されなくて，めちゃめちゃ悩んでました．

全然原因がわからず開発に使っていたionicの問題かと思って色々調べたり，iphoneの実機上でなら動くかと思って実機上でビルドしてみたり(実機のビルドも最初上手くいかなかった)大変でした．
STM32CubeMXでピン設定してVScodeでビルドする

もちろん先人たちの努力がありまして（感謝！）

https://qiita.com/yosihisa/items/8830adf65022d21465c4
https://qiita.com/uhey22e/items/51ddc3145b9f91a33b11

偶然ながら自分が見つけた手順を残しておきます。要するにこれを使います。

https://marketplace.visualstudio.com/items?itemName=bmd.stm32-for-vscode

STM32CubeMXでは，Project Manager で， Makefile を作る設定にして generate code を実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/aa8720a6-67ea-7fb7-a443-6f08b2372ed0.png)

VScodeで stm32-for-vscode を探してインストールします。誘導に従って toolchain をインストールします。（画像は公式から）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/c3f9fb4e-284e-8eee-2631-8bf5ad48f646.png)

STM32CubeMX で作業したフォルダーを VScode で開いて， Build なりなんなりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533274/c2dc0280-d055-5714-89c8-54657b18d9b6.png)

私の NUCLEO-F303K8 の環境では無事 Flash および Debug までできました。ただし，Debug では，ペリフェラルのレジスターが見えません。惜しい！
【第13章】Railsチュートリアルでheroku pg:reset DATABASEを実行時に警告がでる

[Railsチュートリアル第13章(第6版)](https://railstutorial.jp/chapters/user_microposts?version=6.0#code-micropost_model_image_validation)で、herokuでレコードを削除する際に手間取ったので備忘として記録する。

#①heroku pg:reset DATABASEを実行すると警告がでる
チュートリアル終了時にherokuのDBをリセットしようとすると、```Warning: Cannot open browser```が表示されて実行されない。

#②解決方法
 ```heloku login --interactive```を実行すると、正常にログインできる。
参照：https://qiita.com/yadon/items/db3ec786ec410990cec6

#③再度heroku pg:reset DATABASEを実行
表示されるメッセージ通りに入力すれば、成功する。
参照：https://qiita.com/kakiuchis/items/5597354b1901c1371c9e
starship で任意のディレクトリ配下にいる時だけ、必要な情報を出すようにしてみた。

こんにちは。

starship の設定をしてたら一晩経っていたので、個人的に嬉しいと思う設定を紹介したいと思います。

今回はある特定のディレクトリ配下にいる時に、欲しい情報をプロンプトに添えて出しておく設定になります。

![スクリーンショット 2021-09-12 20.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172077/6ce9cf0d-81c0-064b-1bc4-c31133123e17.png)

![スクリーンショット 2021-09-12 21.09.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172077/03a39891-5299-1e7a-b702-5fbdf3d24e84.png)

例えばGCPとAWSを扱う複数のプロジェクトがあった時、デプロイ先がGCPのプロジェクトであればAWSの情報はノイズになりますよね。
そういった時、この設定をすることで、作業に必要な情報を選択してプロンプトの表示に出すことが出来るようになります。

なお私自身のシェル環境はfishとなりますので、適所でお読み替え下さい。

[starshipのカスタム設定](https://starship.rs/ja-JP/config/#custom-commands) を利用します。

例:

```toml:$HOME/.config/starship.toml

format = """
${custom.projectName}\
...省略
"""

[custom.projectName]
# ...

```

トップレベルのformatにカスタム設定の適用場所を決め、他の設定と同じように下部で具体的な設定を書いていきます。

この時、カスタム設定で注意すべきこととして、command, when で実行されるコマンドは現在のシェルに渡される点です。

つまり今時点で実行可能なコマンドをここに記述ができるので, いつ表示させるか, 何を実行するのかの選択肢はとても広いことになります。


今回は when に渡すコマンドを、今いるディレクトリ構造のどれかに、指定するディレクトリ名を含んでいる場合に 終了ステータス0 を返す処理になるように設定します。

fish シェルの場合, $HOME/.config/fish/functions で関数を定義しておけば、どこからでも呼び出し可能なのでそこに定義します。
(bashやzshでも同様の考え方で自由に定義できます。/usr/local/bin等に実行可能なスクリプトとして置いておくのもありですね）

```shell:$HOME/.config/fish/functions/am_i_in_the.fish
function am_i_in_the
  string match -r $argv $PWD
end
```

これでfishシェルに `am_i_in_the XXXX` と渡すことで 今のディレクトリ構造に XXXX を含むと 終了ステータスが0で返るようになりました。

```toml:$HOME/.config/starship.toml
# ...

[custom.projectName]
when = 'am_i_in_the projectDirName'
# ...
```

when にそのまま設定します。

次に command ですが、こちらに渡すコマンドは、実行結果がプロンプトに表示させたい内容になるよう作られたものにしていきます。

gcloud に関係する環境変数を表示させたかったので、以下のような関数を作成しました。

```shell:$HOME/.config/fish/functions/get_gcloud_envs.fish
function get_gcloud_envs --description 'get_gcloud_envs'
  set -l GCLOUD_ENVS ""

  set GCLOUD_ENVS $GCLOUD_ENVS (cat $HOME/.config/gcloud/active_config | xargs -I@ awk '/project/{print "gcloud: "$3}' "$HOME/.config/gcloud/configurations/config_"@)

  if set -q SPANNER_PROJECT_ID; and set -q SPANNER_INSTANCE_ID; and set -q SPANNER_DATABASE_ID
    set GCLOUD_ENVS $GCLOUD_ENVS "spanner: $SPANNER_PROJECT_ID, $SPANNER_INSTANCE_ID, $SPANNER_DATABASE_ID "
  end

  echo $GCLOUD_ENVS
end
```

まとまった環境変数が定義されていると表示に使う変数に文字を足し、不足していると足さないといった考え方で組みました。

これも シェル上で `get_gcloud_envs` として呼び出し可能なので、そのまま command に定義します。

```toml:$HOME/.config/starship.toml
# ...

[custom.projectName]
when = 'am_i_in_the projectDirName'
command = 'get_gcloud_envs'
# ...
```


あとは 表示のさせ方について設定すれば、OKです。

色々試した結果、カスタム設定内のフォーマットで改行は行わず、表示するものが無ければ空行、あればそこに表示するといった形が良いと思いました。

この場合、トップレベルのフォーマットと、カスタム設定のフォーマットの2箇所を意識する必要がありました。

```toml:$HOME/.config/starship.toml
format = """
${custom.projectName}\
$line_break\
...省略
"""

# ...

[custom.projectName]
when = 'am_i_in_the projectDirName'
command = 'get_gcloud_envs'
format = "[$output]($style) "
style = "#707070"
```


以上となります。
快適なstarshipライフを🎉
Linux: 自作サービスをsystemdに登録して自動起動させてみた

新しいソフトウェアをインストールした際に使用したのでメモ。

###### 実施環境：

```Linux:Linux
[root@testhost ~]# uname -a
Linux testhost 4.18.0-331.el8.x86_64 #1 SMP Thu Aug 19 16:49:03 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
[root@testhost ~]# echo $SHELL
/bin/bash
```

 Linux においてサービスの自動起動を行う方法はいくつかあります。
かつては sysVinit が有名でしたが、最近の主流は systemd を用いたものとなっています。
そこで、以下の自作のスクリプトを自動起動に登録してみます。

```Linux:/usr/local/test/test.sh
#!/bin/bash

while true
do
    sleep 10
done

exit 0

```

まず、 /usr/lib/systemd/system 内に設定ファイルを作成し、以下のように書き込みます。
ファイル名は拡張子が .service であれば何でも良いのですが、今回は test.service としました。

```Linux:/usr/lib/systemd/system/test.service
[Unit]
Description = TEST

[Service]
ExecStart   = /usr/local/test/test.sh
Type        = simple

[Install]
WantedBy    = default.target

```

上記のファイル内の項目については以下の通りです。他にも細かい設定はありますが、今回は割愛します。

* Description：サービスの説明。今回は TEST としましたが、わかれば何でも良いです。

* ExecStart：サービスの起動コマンド。フルパスで、引数が必要な場合は引数も含めて記載してください。

* Type：サービスの起動タイプ。今回は実行したコマンド(スクリプト)自体が起動し続けるタイプなので simple となります。コマンド自体は終了し子プロセスが生き続けるタイプの場合は forking を指定してください。

* WantedBy：サービスが自動起動する環境。CUI( multi-user.target )の場合だけでもよいですが、基本全環境( default.target )でよいかと思います。

次に、 systemctl daemon-reload を実行し設定ファイルの再読み込みを行います。
この時点で、自作のスクリプトを systemd から管理できるようになっています。

```Linux:Linux
[root@testhost ~]# systemctl daemon-reload
[root@testhost ~]# systemctl start test.service
[root@testhost ~]# systemctl is-active test.service
active
```

では、いよいよこのスクリプトを自動起動の対象に設定します。
そのためには、 systemctl enable <サービス名>.service を実行します。
systemctl is-enabled <サービス名>.service を実行して enabled と表示されれば登録済みです。

```Linux:Linux
[root@testhost ~]# systemctl enable test.service
Created symlink /etc/systemd/system/default.target.wants/test.service → /usr/lib/systemd/system/test.service.
[root@testhost ~]# systemctl is-enabled test.service
enabled
```

早速OSを再起動し、サービスが自動起動していることを確認してみてください。

```Linux:Linux(再起動後)
[root@testhost ~]# systemctl is-active test.service
active
```
Tech系Podcast


<article>
<h2><a href="https://shiganai.org/">しがないラジオ</a></h2>
<p>大手SIerからWeb系企業に転職したパーソナリティーの2人がゲストともに、転職やキャリアなどについて雑談しているラジオ。</p>
</article>
<article>
<h2><a href="https://fukabori.fm/">fukabori.fm</a></h2>
<p>技術的な話についてゲストに質問していく形で深ぼっている。司会の方のまとめが上手く難しい話が多いが分かったような気にさせてくれる。</p>
</article>
<article>
<h2><a href="https://turingcomplete.fm/">turingcomplete.fm</a></h2>
<p>低レイヤに関するポッドキャスト。全然専門外の話かつレベル高いが、なぜか流していて苦にならない</p>
</article>
Reactを基本からまとめてみた【10】【React Hook (useState)③】

##はじめに
####学習するに至った経緯
2020年より、未経験からエンジニアへの転職を目指し、某プログラミングスクールへ通う。入学後、『Ruby』を未経験から学ぶ人が多いのと『Ruby』の求人が思っていた以上に少ないので、卒業後、フロントエンドのエンジニアを目指す事に。
Reactの学習した事を言語化し、認識の深化による備忘録として記載。

##useStateとは
関数コンポーネント内でstateを保持するためのフック。

##フック(Hookとは)
React16.8で追加された新機能で、関数コンポーネントにstateやライフサイクルといったReactの機能を"接続する(hook into)"ための関数のこと。

##useStateを使うと何ができるのか
useStateを用いることで、コンポーネントに状態(state)を持たせることができる。
状態(state)とは、コンポーネントに管理され、プライベートであるべき値のこと。

##useStateの使い方
```sample.js
1.useStateによるstateの宣言
const [state:現在の状態, setState:更新関数] = useState(initialState:初期値)

2.stateの更新
setState:更新関数(newState:新しい値)

3.具体例
const [messeage, setMesseage] = useState('Torahack is comment')
const [likes, setLikes] = useState(0)
const [isPublished, setIsPublished] = useState(false)
setIsPublished(true)
```

##引数を使って更新する
```sample.js
//入力ホームでよく使うソースコード
import React, {useState} from 'react';

const TextInput = () => {
 const [name, setName] = useState('')

const handleName = (event) => {
 setName(event.target.value)
}
//onChangeイベントでhandleName関数に渡す
//handleName関数のパラメータであるeventを更新関数に渡す
 return (
  <input
    onChnage={(event:onChangeイベントの戻り値) => handleName(event)}
    type={'text'}
    value={name}
  />
 );
};
``` 

##prevStateを活用する

####prevState とは
以前の状態 にアクセス・参照して 値を変更する こと。

```sample.js
//useStateの更新関数で使える特殊なprevState
import React, {useState} from 'react';
//prevStateは更新前のstate
const Counter = () => {
 const [count, setCount] = useState(0)
 const countUp = () => {
  setCount(prevState => prevState +1)
}
 const countDown = () => {
  setCount(prevState => prevState -1)
}
//prevStateは更新を加えてreturn
  return (
   <div>
    <p>現在のカウント数:{count}</p>
    <button onClick={countUp}>up</button>
    <button onClick={countDown}>Down</button>
   </div>
　);
};
```
##ON/OFFを切り替えるボタン

```sample.js
import React, {useState} from 'react';

const ToggleButton = () => {
  const [open, setOpne] = useState(false)
  
  const toggle = () => {
  setOpen(prevState => !prevState)
}
//prevStateで受け取った値を!で反転してreturnする
 return (
  <button onClick={toggle}>
//参考演算子によってopenがtrune/falseで表示を切り替える
    {open ? 'open':'close'}
  </button>
);
};
export default ToggleButton;
```


##参考サイト
[#07 新・日本一わかりやすいReact入門【基礎編】頻出するuseStateのケース3選]
(https://www.youtube.com/watch?v=7MzVcLAtl8g&t=393s)
[(React) prevState について]
(https://ratio.ym-tane.com/development/react-prevstate/)
Pythonのgoogletransを用いた翻訳

## はじめに
　今回はgoogle翻訳のAPIであるgoogletransを用いて、英語を日本語に翻訳するプログラムを作成した。その時に学習した内容をここにメモする。

## googletransとは
　googletransとはGoogle翻訳の文字列をhttp方式で渡すことで翻訳した内容が返ってくるAPIである。今回はこちらを用いた翻訳プログラムをPythonによって作成した。

## 準備段階
　今回の環境ではwsl2にPython3.8.1で行った。まずはpythonのモジュールのインストールについては下記のコマンドによって行った。

~~~
pip3 install googletrans==4.0.0rc1
~~~

バージョンの指定をしない場合に、googletrans3.0.0がインストールされてしまいそこで躓いた。3.0.0だと 'AttributeError' が生じてしまうため、注意が必要になる。

##プログラミング
　今回使用したプログラミングを以下に記す。

~~~python:translate.py
from googletrans import Translator

def translate(text):
    translator = Translator()
    changetext = translator.translate(text, dest='ja')
    return changetext.text

if __name__ == "__main__":
    text = 'Nice to meet you'
    t = translate(text)
    print(t)
~~~

プログラミングの内容としては、text内にある文字列を日本語に翻訳しプリントする処理を行う。上記のプログラミングを実行した結果が以下になる。

~~~
会えて嬉しい
~~~

##最後に
今回google翻訳のAPIであるgoogletransを用いた翻訳プログラムを作成した。今後は、このプログラミングを利用し、LINEと組み合わせた翻訳アプリケーションを作成しようと思う。
"context requires credentials to be passed as environment variables"の対処法

##エラー内容
[Docker ComposeのAmazon ECSデプロイを試してみた](https://tech.smartcamp.co.jp/entry/docker-compose-with-ecs)

上の記事を参考にAWSのコンテナ基盤であるECSの概要を理解しようとぽちぽち触っていたところ、contextを作成するために下のコードを実行すると記事にはない選択項目が出現。

```terminal
$ docker context create ecs myecscontext
```
↓

```terminal
> AWS secret and token credentials
  AWS environment variables
```

挙動を確認するためと軽い気持ちで2つめのAWS environment variablesを選択したところ,

contextの作成に成功したようですが記事のように内容の入力が求められませんでした。

```terminal
Successfully created ecs context "myecscontext"
```

気にせず作成したcontextをuseするために下のコードを実行すると悲劇が起きました。

```terminal
$ docker context use myecscontext
```
docker compose upすると

```terminal
$ docker compose up
```

↓

```terminal
context requires credentials to be passed as environment variables
```

当然何も入力していないcontextなのでこういう挙動なのだなと確認してcontextをdefaultに戻そうとすると

```terminal
$ docker context ls
```

↓

```terminal
context requires credentials to be passed as environment variables
```

contextが確認できません。

確認はできなくてもdefaultに戻せれば...と思って実行するも

```terminal
$ docker context use default
```

↓

```terminal
context requires credentials to be passed as environment variables
```

完全にハマってしまいました。コマンド操作をするために元に戻す操作自体ができなくなってしまったのです。

しかしエラー文であるcontext requires credentials to be passed as environment variablesで検索しても全然情報が出てきません。

日本語の情報だけでは解決策がなかったのでついに愛用のMacを詰ませてしまったかと覚悟しましたが、英語のstackoverflowにて同じ悩みを抱えている人を発見。その方も情報が少ないことに悩んでいるようでしたが、回答者の1人が解決策を提示していました。。
[Passing environment variables to `docker-compose` when using ecs context]
(https://stackoverflow.com/questions/67813708/passing-environment-variables-to-docker-compose-when-using-ecs-context)

## 解決策

```terminal
$ AWS_SECRET_ACCESS_KEY=dummy AWS_ACCESS_KEY_ID=dummy AWS_DEFAULT_REGION=dummy docker context ls     
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm
myecscontext *      ecs                 credentials read from environment                                                             
$ AWS_SECRET_ACCESS_KEY=dummy AWS_ACCESS_KEY_ID=dummy AWS_DEFAULT_REGION=dummy docker context use default
default
$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default *           moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm
myecscontext        ecs                 credentials read from environment                                                             
$ docker context rm myecscontext
myecscontext
```
##まとめ

どうやらAWS environment variablesは文字通りAWSの環境変数を直接ターミナルに打ち込んでデプロイ できる仕組みのようでデタラメでも何かしらを環境変数に代入して実行する必要があったようです。

もちろん何がわからないかもわからない状態で操作してしまった私に非がありますが、どう言ったテンプレートで入力するべき状況で起きているエラーなのかを最低限エラーメッセージとして書いていて欲しかったなと感じました。

今の私には自力でこの解決方法にたどり着くことは不可能だったので、私のように時間を取られる人が1人でも減るように共有したいと思います。
【勉強記録】正規表現の分解

## 目次

- 趣旨
- マッチの確認
- 分解してみる
- 振り返り
- 参考サイト

## 趣旨
正規表現について学習しました。
今回は[こちら](https://designsupply-web.com/media/knowledgeside/1640/)で公開されている正規表現のサンプルをいくつかお借りして、それを分解することでどのような表現で実現しているのか確認してみたいと思います。

## マッチの確認
Pythonの標準モジュールである、re(正規表現操作)を利用して下記の通り確認していきます。
（手元ではこのコードで試しています。）

``` regular_expression.py
import re

numbers = "123"
# 「数字を1文字以上繰り返す」ことの確認
confirm = re.search('[0-9]+', numbers)
# =>　<re.Match object; span=(0, 3), match='123'>
```

## 分解してみる
本題です。
### 名前
```Python
^[ぁ-んァ-ヶー一-龠]+$
```
| 使われている表現 | 説明 |
|:-:|:-:|
|  ^ | 先頭文字にマッチ  |
| []  |  文字の集合を表す |
|  ぁ-ん | ひらがな  |
|  ァ-ヶ |  カタカナ |
| 一-龠  | 漢字(Unicode JIS内字)  |
|  ー | 伸ばし棒  |
|  + | 直前の表現を1回以上繰り返す  |
|  $ |  末尾にマッチ |
言い換えると、
`先頭から末尾までが、一文字以上のひらがな・カタカナ・漢字・ー(伸ばし棒)のいずれかで構成されている`
ちなみに、ひらがなの表現が小文字の「ぁ」から始まる理由は[Unicode対応 文字コード表](http://ash.jp/code/unitbl21.htm)の並びが、ぁ、あ、ぃ、い…という並びになっているからです。他も同様です。

### 電話番号
```Python
^0\d{1,4}-\d{1,4}-\d{3,4}$
```
| 使われている表現 | 説明 |
|:-:|:-:|
| ^  | 先頭文字にマッチ  |
| \d  |  [0-9]と等価 |
| {1,4}  | 直前の表現を1~4回繰り返す  |
|  $ | 末尾にマッチ  |
`先頭が0＋1～4文字の数字、1～4文字の数字、末尾が3～4文字の数字で構成され、-(ハイフン)で繋がっている`

### メールアドレス
```Python
^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$
```
| 使われている表現 | 説明 |
|:-:|:-:|
|  ^ |  先頭文字にマッチ  |
|  a-zA-Z0-9 | アルファベットの大文字/小文字/数字  |
|  + | 直前の表現を1回以上繰り返す  |
| \._-  |  記号 |
| *  | 直前の表現を0回以上繰り返す  |
|  $ | 末尾にマッチ  |
`先頭文字と@の次の一文字はアルファベットか数字、加えて@以前はアルファベットか数字か定められた記号を0回以上、@以降は1回以上使用して構成されている`
つまり最低限あればいいのは@前に1文字、@以降に2文字ということになります。`1@23`でマッチします。
尚、Pythonではバックスラッシュがエスケープ文字なので、このままでは"\"は認識されませんでした。
"\\\"にしても変わらず、解決に至らなかったため検証としては不完全なものになってしまいました…。

### 振り返り
以前架空のECサイトを作成した際のバリデーションを設定するために今回取り上げた正規表現を使わせて頂いておりました。
改めて調べてみるとどういう仕組みで実現していたのかがよくわかりました。また、せっかくなら条件をもう少し厳しくしたいと思う点もあり、勉強した点を踏まえて変更してみたいと思います。
日本語として正確に表現するのはかなり冗長になるのである程度省略したつもりですが…ご覧の通りです。記号の強みですね。

## 参考サイト
https://designsupply-web.com/media/knowledgeside/1640/
https://docs.python.org/ja/3/library/re.html#module-re
https://www.ogiso.net/wiki/index.php?%BC%F8%B6%C8%BB%F1%CE%C1/%C0%B5%B5%AC%C9%BD%B8%BD
https://ameblo.jp/tondemonight/entry-1011710