OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoder Beginner Contest 167備忘録

#初めに
この記事を参考にしようと思って来た人。残念。
A,B,C,D理解済み
#A - Registration

```python
s==t[0:-1]#(というか[:-1]でもよかった気が...)
```

#B - Easy Linear Programming
順に枚数を引いていけばok
汚いソースコード。

```python
def j():
    a,b,c,k=map(int,input().split())
    o=0
    x=k
    if a!=0:
        o+=a
        k-=a
        if k==0:
            return a
        elif k<0:
            return x
    if b!=0:
        k-=b
        if k<=0:
            return a
    if c!=0:
        k-=c
        o-=c
        if k==0:
            return o
        elif k<0:
            return o-k
print(j())
```

#C - Skill Up
飛ばした。
全探索苦手。
次までには学ばねば。

追記
bit探索というものでできるそうだ。
なので[学んで](https://qiita.com/gogotealove/items/11f9e83218926211083a)挑戦してみた。
結果、一発クリアだった。bit探索法は便利だということが分かった。

```python
n,m,x=map(int,input().split())
item=[list(map(int,input().split()))for i in range(n)]#金、アルゴリズムUp数
bag=[]#条件を満たす本の買い方
for i in range(2**n):#すべて調べる
    temp=[]#買う本
    job=[0]*m#理解度
    for s in range(n):#全桁を調べる
        if (i>>s)&1:#買うのであれば
            temp.append(s)#買う本を追加
            for y in range(m):
                job[y]+=item[s][y+1]#理解度を足す
    for s in range(len(job)):
        if job[s]<x:#もし、理解度がX未満であればbreak
            break
    else:#理解度がすべてX以上ならば
        money=0
        for s in temp:#合計金額を算出
            money+=item[s][0]
        bag.append(money)
#買う組み合わせが1以上なければ-1を出力
print(min(bag) if len(bag)>=1 else -1)
```
#D - Teleporter
K回for回したらTLEにしかならないのでループの最初と最後で余剰すれば行ける。
と思ったのに行けなかった。だれか教えて。ちなみに問題文の例はできている。

```python

n,k=map(int,input().split())
a=[int(i)-1 for i in input().split()]
ed=[False]*n
go=0
c=0
cc=0
while not ed[go]:#既に通っていたら終了
    print(a[go]+1)
    ed[go]=True
    go=a[go]
    c+=1
ed=[False]*n
print()
while not ed[go]:#二回目のループは違う可能性があるため6,5,2,5,3,2の場合、6,2,5,3,2,5,3,2,5,...となる
    print(a[go]+1)
    ed[go]=True
    go=a[go]
    cc+=1#別変数で保存
print()
for i in range((k-c)%cc):
    print(a[go]+1)
    go=a[go]
print()
print(go+1)
```

追記
whileをまとめて、printをforで回さずに、値を保存して、一回もループをしていなかった場合の出力を追加したらできた。

```python
n,k=map(int,input().split())
a=[int(i)-1 for i in input().split()]
p=0
visited=[0]*n
first=[]
roop=[]
while visited[p]!=2:#二回通っていたらやめる
    if visited[p]==0:#初めて通った
        first.append(p)
    else:#一回通った
        roop.append(p)
    visited[p]+=1#通った跡をつける
    p=a[p]#テレポート
if len(first)>k:#一回もループしないのなら
    print(first[k]+1)#最初のk番目
else:
    print(roop[(k-(len(first)-len(roop)))%len(roop)]+1)#そうでなければkから一回目のループと二回目のループを引いて二回目のループの回数の余剰
```
#最後に
EとFは辿り着けなかった。
3回目の挑戦だったが難しい。もっとアルゴリズムを学び、論理的思考ができる頭にしなければと思った。ちなみに新Ratingは68。
【Maven】をWindows10にインストール

# MavenをWindows10にインストールする手順を紹介します。


#目次
*  [1. ダウンロード](#1ダウンロード)
*  [2. フォルダ格納](#2フォルダ格納)
*  [3. 環境変数登録](#3環境変数登録)
*  [4. コマンド確認](#4コマンド確認)

#1.ダウンロード
以下のサイトにアクセスします。
https://gradle.org/install/

Binary zip archiveから「apache-maven-3.6.3-bin.zip」をダウンロードします。
※2020/05/10時点の最新バージョンは「3.6.3」でした。

#2.フォルダ格納
今回はCドライブ直下に配置します。


#3.環境変数登録
3-1.環境変数設定を開きます。
　※「コントロール パネル->システムとセキュリティ->システム->システムの詳細設定->環境変数」

　3-2.システム設定変数にmavenを新規登録します。
　　変数名：M2_HOME
　　変数値：C:\apache-maven-3.6.3

　3-2.システム設定変数のPathにMavenを追加登録します。
　　変数値：%M2_HOME%\bin

#4.コマンド確認
```Console:Windowsコマンド
rem Mavenバージョン確認コマンド
mvn -v

Maven home: C:\apache-maven-3.6.3\bin\..
Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: C:\Program Files\Java\jre1.8.0_181
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

```
英語で導入したUbuntu環境の日本語化

# はじめに

　Azureで仮想のUbuntu環境を構築した際にCUIもGUIも英語表記になっていたので、
　それを日本語化したときの作業について簡単にまとめる
　試行錯誤しながら手当たり次第にやって出来たので、事後のメモになっており所々抜けがあるかもしれないです。

# 日本語化の為の作業の概要

　調べると以下の手順を踏む必要があるようです。

1. 日本語関連のパッケージをインストール
2. ロケールを日本語に設定

1
以下のコマンドを実行し日本語関連のパッケージをインストール

  ```sudo apt-get install language-pack-ja-base language-pack-ja
```
2
ロケールを日本語に設定する
 ```sudo update-locale LANG=ja_JP.UTF-8 LANGUAGE=”ja_JP:ja”
```

ここでcatコマンドを使って2番が適用されているかを確認してみると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617980/a7dcd710-f9fd-8e42-7285-f5ea5a361cfd.png)
2番で行ったロケールの設定が反映されています。

これでCUIは日本語か出来ました。

# デスクトップの日本語が文字化けしている…

　RDPで接続してみると、日本語の部分が□になっており、文字化けしていました。
　これを治すのに時間がかかってしまいました。

　日本語のフォントが入っていなかったことが原因のようでした。
　なので以下のコマンドで日本語フォント「Takaoフォント」をインストールする。
　```sudo apt install fonts-takao
```
RDP接続で見てみると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617980/69dba1e9-a5f6-8907-6595-9d1022b12887.png)
文字化けせず日本語が表示されている。
Atcoder ABC167 A-DをPythonで

#A. Registration
新しいidの$|S|-1$文字目までが同じであればYes、そうでなければNoを出力

```ABC167a.py
a=input()
b=input()
s=len(a)
if b[:s]!=a:
    print("No")
else:
    print("Yes")
```

#B. Easy linear programming
$k$が$a$よりも少なければ$a$のカードを$k$枚選ぶ。
$k$が$a+b$よりも少なければカードの和は$a$。
そうでなければカードの和は$a-(k-(a+b)))$

```ABC167b.py
a,b,c,k=map(int,input().split())

if k<=a:
    print(k)
elif k<=a+b:
    print(a)
else:
    print(a-(k-(a+b)))
```

#C. Skill up
コンテストの締切5分後にACでした。悔しい。
$N<12$なので、ビット全探索して条件を満たす最低価格を更新していけばいいです。

```ABC167c.py
n,m,x=map(int,input().split())
l=[]

for i in range(n):
    a=list(map(int,input().split()))
    l.append(a)
ans=99999999
for i in range(2 ** n):
    bag = []
    for j in range(n):  #bit全探索
        if ((i >> j) & 1): 
            bag.append(l[j])  
    skill=[0]*m
    enough=[0]*m #各スキルにつき、xを超えているかどうかを判断
    money=0
    for sub in bag:
        money+=sub[0]
        for kk in range(1,m+1):
            skill[kk-1]+=sub[kk]
            if skill[kk-1]>=x:
                enough[kk-1]+=1
    if 0 not in enough: #全てのスキルがxを超えていたら価格を計算
        if ans>money:
            ans=money#最低価格を下回っていたら更新
if ans==99999999: #初期値からの変更がなければ-1を、そうでなければ最低価格を出力
    print(-1)
else:
    print(ans)
```

#D. Teleporter
全てのテレポッドがどこかの街に行くので、高々$N$回以内にループに突入します。例えば例1では$1=>3=>4=>1...$, 例2では$1>=6=>2=>5=>3=>2...$といった具合に。ループに突入する前のテレポート回数を$t1$、突入した後のループ1回のテレポート回数を$t2$とすると、最後のテレポートの1つ前の位置は$(k-t1) mod t2$になります。あとはその場所の移動先を出力するだけです。行数も多いしコードも汚いので、もっと効率的な解き方があるのかもしれません。

```ABC167d.py
n,k=map(int,input().split())

a=list(map(int,input().split()))

l=[1]
di={}
di[1]=1

for i in a:
    b=a[l[-1]-1]
    if b in di:
        x=b
        break
    l.append(b)
    di[b]=1
t1=0
for j in l:
    if j==x:
        break
    else:
        t1+=1

t2=len(l)-t1
if k<=t1:
    print(l[k])

else:
    aa=(k-t1)%t2
    print(l[t1+aa])
```

またDまでで時間を使い果たしてしまいました。来週こそは・・・
[SwiftUI]MapKitのAnnotationを動かす 

SwiftUIでMapKitのアノテーションを自動で動かす画面を作りました。

## 完成図
![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501910/2a176360-23d1-2697-333b-e7a3c6b7f8c6.gif)

## コード
```swift
import SwiftUI
import MapKit

struct MapAnimationView: View {
    @State dynamic var longitude:Double = 139.745451
    @State dynamic var latitude:Double = 35.658577
    var targetLongitude:Double = 143.1212
    var body: some View {
        VStack{
            Button(action:{
                self.move()
            }){
                Text("Move")
            }
            AnimationMapView(lon:self.$longitude, lat:self.$latitude)
        }
    }
    
    func move(){
        self.longitude = self.targetLongitude
    }
}


struct AnimationMapView: UIViewRepresentable {
    @Binding dynamic var lon:Double
    @Binding dynamic var lat:Double
    
    func makeUIView(context: UIViewRepresentableContext<AnimationMapView>) -> MKMapView {
        let view = MKMapView(frame: .zero)
        
        // 初期位置にピンを追加
        let annotation = MKPointAnnotation()
        annotation.coordinate = CLLocationCoordinate2D(latitude: self.lat, longitude: self.lon)
        view.addAnnotation(annotation)
        return view
    }
    
    func updateUIView(_ uiView: MKMapView, context: UIViewRepresentableContext<AnimationMapView>) {
        print(uiView.annotations)
        
        // MapAnimationViewの座標が更新された場合、アニメーションで移動させる
        if uiView.annotations.count > 0{
            let annotation = uiView.annotations[0] as! MKPointAnnotation
            let targetPosition = CLLocationCoordinate2D(latitude: self.lat, longitude: self.lon)
            UIView.animate(withDuration: 4, animations: {
                annotation.coordinate = targetPosition
               }, completion: nil)
        }
    }
}

```

## 備考
swiftUIのアニメーション機能を利用してUIKitを動かそうとしたができませんでした...
日常的な生産性の向上

日常的な生産性の向上
１．商談を編集中に、同僚から、次回のマネージャへのプレゼンテーションに必要な情報について電話がかかってきました。メモを作成して詳細を後で確認できるように保存する最良の方法はどれですか?
２．再設計された Lightning Experience ホームページでは、[アシスタント] を使用して何ができますか?
３．Lightning Experience でキーボードショートカットを使用して何ができますか?

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/23cfd5a7-73ff-e36b-e08a-e94bccb0b08a.png)
Raspbianにaptでnginx+PHP7.3を導入

# 導入経緯
Raspberry Pi４を購入してWebサーバーを構築します。
Apacheのほうが慣れているのですが、nginxに乗り換えたいと思ったので実行してみました。

# nginxのインストール
最近はapt-getよりaptを使うことが多いですので、説明もaptで統一します。

まずは、「nginx」のインストールコマンド
`$ sudo apt install nginx`

「nginx」の起動
`$ sudo systemctl start nginx`

nginxが起動したら、ブラウザからRaspberry PiのIPアドレスにアクセスするか、Raspberry Piのブラウザからlocalhostにアクセスしてnginxの初期ページが閲覧できることを確認しましょう。

# PHP7.3のインストール
PHPは今回「7.3」を使います。
「php7.3」のインストールコマンド
`$ sudo apt install php7.3 php7.3-fpm php7.3-mbstring php7.3-gd php7.3-xml`
※WordPressとか使うことをがあったのでとりあえずmbstringとか一式入れてます。

nginxでPHPが使えるように設定を変更します。
`$ sudo vi /etc/nginx/sites-available/default`

44行目に「index.php」を追加

```
43    #Add index.php to the list if you are using PHP
44    index index.html index.htm index.nginx-debian.html index.php;
```

56〜63行目のコメントアウトを削ります。
今回は、fpmをインストールしていますので61〜62行目のコメントアウトはそのまま残します。
ただし、コメントアウトを残す必要がある箇所もあるので以下のように編集しましょう。

```
 56    location ~ \.php$ {
 57        include snippets/fastcgi-php.conf;
 58       
 59        # With php-fpm (or other unix sockets):
 60        fastcgi_pass unix:/run/php/php7.3-fpm.sock;
 61        # With php-cgi (or other tcp sockets):
 62        #fastcgi_pass 127.0.0.1:9000;
 63    }
```

php.iniも変更します。
`$ sudo vi /etc/php/7.3/fpm/php.ini`

793行目のコメントアウトを削除して編集

```
793 ;cgi.fix_pathinfo=1
↓↓↓↓↓↓↓
793 cgi.fix_pathinfo=0
```

「php7.3-fpm」を起動します。
`$ sudo systemctl start php7.3-fpm`

「nginx」を再起動します。
`$ sudo systemctl restart nginx`


# nignxとPHP7.3を自動起動するように設定
以下のコマンドを実行して、起動時に自動起動するようにします。
`$ sudo systemctl enable nginx`
`$ sudo systemctl enable php7.3-fpm`
これで、次回起動時から自動で起動してくれます。
【Python】素人が機械学習を始めるにあたって

#はじめに
この記事はプログラミング初心者の筆者が機械学習をすすめる上で、参考になったことを備忘録がてら記すものです。

素人目線で参考になった情報などを記載していきます。

#機械学習のために参考になったサイトの紹介

何かとトレンドの機械学習を私も試してみたくなり、いちから挑戦しています。

###機械学習とはなんぞや

まず機械学習とは何かを簡単に学べるサービスの紹介です。

####其の一、aidemy
無料の会員登録が必要だが、動画で機械学習の入門を学べます。
無料のコンテンツはそこまで多くないが、まず概要をサクッとさらいたい人はよいかも。
Pythonの初心者コースもあるので、プログラムを触ったことがない人でもとっつきやすいかも。
>https://aidemy.net/

####其の二、codexa
>https://www.codexa.net/
同じく無料の会員登録が必要だが、こちらは線形代数や統計など機械学習に必須となる部分も無料で学べます。
（めちゃくちゃ助かりました）


#実際に手を動かすにあたって行ったこと
inputを上から行い、次はoutputということで実際にものを作ってみたいと思います。

今回サンプルとして作るのは**「おすすめ機能」**です。
amazonとかでもあるアレです。

参考にしたのは、以下のサイトです。
初心者向けで丁寧に記載されており、とてもわかりやすかったです。
>https://www.codexa.net/collaborative-filtering-k-nearest-neighbor/

####やってみてハマった2つのことを紹介
上の記事を参考にすればほぼコピペでいけると思うのですが、少しハマった部分もあったので書き留めておきます。

1. （そもそも）Atomでのautocomplete-pythonが作動しない
環境を作るにあたりエディターはAtomを使用したのですが、其の際にインストールしたautocomplete-pythonが作動せず…
ググったところ、
「C:\Users\username\.atom\packages\autocomplete-python\lib\jedi\parser」
においてあるgrammarX.X.txt（Xはpythonのver）というファイルのverが自分の環境のPyhtonのVerと合っていないとだめでした。（StackOverFlowにそれらしき投稿があり、そちらを参考にしました。）

2. MemoryErrorの罠
チュートリアルの記事通り進め、はじめは順調だったものの
出ました**MemoryError: Unable to allocate …**

大量のデータを扱うので、この手のエラーは機械学習にはつきもののようですね。
試した解決方法は以下の2つです。

- daskを使う
メモリに乗り切らないような大容量データを扱う際のライブラリだそうです。
今回MemoryErrorが起きたのはpivotの処理でした。
其の部分だけを分散して処理するような書き方を試行錯誤したのですが、うまくいかずあきらめました…
（誰か教えてほしい…）

- gc.collect()　で手動でメモリを解放する
初歩的なことですが、たぶんあんまり意味なかった。


- データの件数そのものを減らす
今回はチュートリアル的な意味合いで始めたこともあり、さくっとこちらで解消させました。
具体的には、「members （当該のアニメのグループに所属しているユーザー数）が10,000以下のデータを足切り」という処理があるのですが、其の数字を徐々に増やしただけです。

##実行結果
上記の様にごまかしながらですが、ひとまずチュートリアルを終える事ができました。
![WS000005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635205/e258ee2a-cd15-735a-ae62-509a82e30e61.jpeg)

※個人的に好きな灼眼のシャナで実施してみましたが、まぁわかるようなおすすめラインナップです。


##まとめ

機械学習の初歩として、基本的な関数の使い方、データの考察・加工の仕方などがわかり個人的には満足です。
引き続き実務に使えるようなものを作成できるよう精進していきます
.envとは

# 目的・動機
vsCodeでpythonのunsolved importの問題解決時に.envに対して設定をする場面があり、"envってなんぞ？？？"となったため調べて見ました.　解釈が間違っている点や、文章に不備がある点は教えていただけると幸いです。
# 説明
.envで検索すると以下の2点のファイルについてと、Unixコマンドについて出てきます。  
## .env(拡張子)
envはenvironment(環境)の略  
環境設定ようファイルにつく拡張子
## env(Unixコマンド)
>「env」は、環境変数の値を設定しつつ、同時に指定したコマンドを実行するコマンドです。環境変数を現在の設定と変えた場合に、あるコマンドがどのように動作するのかを調べることができます。環境変数が全く設定されていない状態で指定したコマンドを実行することも可能です。
[【 env 】コマンド――環境変数を指定してコマンドを実行する](https://www.atmarkit.co.jp/ait/articles/1801/18/news016.html)

# まとめ・最後に
- envは環境変数などに関するもの
- .envはアプリケーション毎に異なる環境設定を用いたいときの詳細を記したファイルの拡張子
シングルファイル C/C++ ライブラリの実装方法


シングルファイル C/C++ ライブラリの概要や利点についてはこちら。
https://qiita.com/syoyo/items/e9d4aff56f691f5b783b

私の知る限りシングルファイルC/C++ライブラリの実装方法には以下の2種類がある（他にもあったら教えてほしい）。

なおシングルファイルC/C++ライブラリを使うメリットはどこでも簡単に動かせることだと思うので、この記事では移植性を損なうコンパイラの拡張機能を使うことは考えない。

## `#ifdef`で宣言と実装を切り替える方法

1ファイルの中に宣言と実装を分けていれておき`#ifdef FOO_IMPLEMENTATION`により切り替える方法。

宣言されている関数を使う時は`#include`して宣言を参照する。
実装したいファイルでは`#define FOO_IMPLEMENTATION`を`#include`の前に書き、実装を読み込む。
実装するのはプログラム内で唯一のファイルである必要がある。

この方法の代表的なライブラリとしては[stb](https://github.com/nothings/stb)や[tinyobjloader](https://github.com/tinyobjloader/tinyobjloader)がある。

この方法の問題はどこで実装するかをプログラマが意識してコントロールしなければならない点だ。
複数個所で実装すると当然リンク時に重複シンボルエラーになる。

この問題はシングルファイルC/C++ライブラリを使ったライブラリの移植性の低下につながる。

例えばライブラリAでstbを使っていた（実装していた）とする。
そのことを知らずに別途stbを実装しているアプリケーションBでライブラリAをリンクすると重複シンボルエラーになる。

## `template` (or `inline`) で書く方法
こちらはC++限定になるが`template`で書く方法。

この方法は`#ifdef`を使う方法よりも流行っていないようだが、例としては[NanoRT](https://github.com/lighttransport/nanort)が挙げられる。
私自身もこの方法で[NanoPM](https://github.com/unclearness/nanopm)というPatchMatchのシングルファイルC/C++ライブラリを作ったことがある（名前はNanoRTをリスペクトしてつけた）。

`#include`するだけで使えるので`#ifdef`を使う方法よりも扱いやすいと私は思う。

`template`の問題としてコンパイル時間と実行ファイルサイズが増加する可能性がある。

また、プログラム全体でバージョンが統一されていないと実行時の挙動が予測できない。
ある`template`ライブラリの`v0.1`を使ったライブラリAと、`v0.2`を使ったライブラリBをリンクすると、同じ名前だが実装が異なるためどちらかのシンボルで上書きされ実行時の挙動が予測できない。

コンパイルとリンクが通ってしまい、さらに実行時も動いたり動かなかったりするのが厄介だ。
シングルファイルではないが[Eigen](http://eigen.tuxfamily.org/index.php?title=Main_Page)でこの問題によく悩まされる。

## 比較

||`#ifdef`方式|`template`方式|
|---|:---:|:---:|
|言語|C/C++|C++のみ|
|コンパイル時間|普通|長め|
|実行ファイルサイズ|普通|大きめ|
|実装ファイルをプログラマが指定|**する**|しない|
|重複シンボルエラー|起きやすい|起きにくい|
|実行時エラー|起きにくい|起きやすい|

この表だけを見ると一長一短だが、`#ifdef`方式の実装ファイルをプログラマが指定するというのがだるすぎるので私は`template`方式推しだ。

## シングルファイルC/C++ライブラリを自作ライブラリに組み込むベストプラクティス

を知りたい。

前述したように単純に自作ライブラリに組み込むとリンクした際に`#ifdef`方式では重複シンボルエラー、`template`方式では実行時エラーになる可能性がある。

そこで`git submodule`などで元のコードを参照するのではなく、コードを改変して自作ライブラリ名前空間に入れたり関数名に自作prefixをつけたりするのが安全だと思う。
が、改変が面倒だし元のコードのバージョンを保持しておくのも面倒なのでもっといい方法を探している。
Electron で mac と win に対応したアプリを作る時のこと。

Electron は node + chrome をパックしてて、一つのソースで複数のプラットフォームで動作するアプリを作れるのですが、実際 Mac でも Win でも動くようにするといくつかはまりどころがあったので、私のはまり方が大きかった順にご紹介しておきます。（Linuxは機会があれば！）

# ショートカット／アクセラレータ

https://github.com/electron/electron/issues/3682

この`issue`にあるように`Window`と`linux`の`chrome`ではいくつかのショートカットがウィンドウ中のテキストに作用するようにハードコードされているようです。
なのでテキスト以外のものを扱う例えばグラフィックエディタのようなものでは、`keydown`もしくは`keyup`イベントで`preventDefault`して明示的に自前のハンドラを呼ぶ必要があります。
今のところ確認してるのは以下のものです。

* Ctrl-A
* Ctrl-C
* Ctrl-V
* Ctrl-X
* Ctrl-Z

# alt キー

https://stackoverflow.com/questions/18655315/why-html-input-onblur-event-raised-when-alt-key-pressed

ここにあるように`windows`では`alt`キー(18)を押すと`Focus`中のエレメントのフォーカスが失われます(`blur`イベントが来ます）。ユーザーから見ると、突然キーが効かなくなったように見えるので、`alt`キーのコンビネーションを使うのをやめるか、使うんだったら`preventDefault`します。

```
const
isWin = process.platform === 'win32'

:
:
	ev => {
		switch ( ev.keyCode ) {
		case 18:	if ( isWin ) ev.preventDefault()	; break
```

# window-all-closed

`Windows`と`Linux`は1画面で1アプリなので、windowが閉じられたら、window-all-closedが来ます。なので`Mac`じゃなければ、app.quit()で終了します。

```
app.on(
    'window-all-closed'
,   () => process.platform != 'darwin' && app.quit()
)
```
# activate

事実上`Mac`でしか用のないイベントです。バックグラウンドに行ったあと、再びフォアグラウンドに来た（例えばドックでアイコンをクリックした）時に来ます。全ウィンドが閉じられている状態（`Mac`でしか起こりえない）だったらファイルを開いたり、新規書類を作ったりします。

```
app.on(
    'activate'
,   ( event, hasVisibleWindows ) => !hasVisibleWindows && 新規書類
)
```

# メニュー

https://www.electronjs.org/docs/api/menu

`Electron`のドキュメントに典型的な例が載っていますので、ここを参考に作っていきます。
Golangの継承(extends)対応テンプレート(goingtpl)を作ってみた

[Golangのインクルード(include)対応テンプレート(goingtpl)を作ってみた](https://qiita.com/kamina/items/64a1f2e238d072273fd8)
を改良して、継承(extends)表記にも対応してみました。
そもそもGoでもテンプレートの継承的な動作はできるのですが、プログラム側で継承元ファイルを指定してあげる必要があります。（のはず。。
それをテンプレート側の記述だけで完結させ、プログラム側は自動で継承元ファイルを読み込むようになるというものです。

というのも最近はもっぱらPython(Django)を使うことが多く、そのテンプレート表記に慣れてしまっ為にGoでも同じように記述できないかなと(笑)

# goingtpl

下記GitHubで公開中です。
[https://github.com/playree/goingtpl](https://github.com/playree/goingtpl)
使い方などの詳細は下記
[https://github.com/playree/goingtpl/blob/master/README.JP.md](https://github.com/playree/goingtpl/blob/master/README.JP.md)

## テンプレートのイ継承(extends)機能
テンプレートファイルに継承元のテンプレートファイルを記述することができます。
テンプレートファイルに `{{extends "xxx.html"}}` のように記述します。

```html:base.html
<!DOCTYPE html>
<html><body>
  <h1>{{template "title" .}}</h1>
  <div style="background-color: #ddf;">
    {{template "content" .}}
  </div>
  <p>Footer</p>
</body></html>
```

```html:page1.html
{{extends "base.html"}}
{{define "title"}}Page1{{end}}
{{define "content"}}
  <p>This is Page1.</p>
{{end}}
```

あとは下記のように専用のパースメソッドを使用して、テンプレートファイルをパースするだけで、extends指定したファイルも一緒にパースされます。

```go:パースメソッド
tpl := template.Must(goingtpl.ParseFile("page1.html"))
```

パース後のHTMLは下記のようになります。

```html:パース後のHTML
<!DOCTYPE html>
<html><body>
  <h1>Page1</h1>
  <div style="background-color: #ddf;">
    <p>This is Page1.</p>
  </div>
  <p>Footer</p>
</body></html>
```

下記はプログラムが側のサンプルです。

```go:サンプル
package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
	"time"

	"github.com/playree/goingtpl"
)

func main() {
	// テンプレートのディレクトリを設定
	goingtpl.SetBaseDir("./templates")

	http.HandleFunc("/test", handleTest)
	log.Fatal(http.ListenAndServe(":8088", nil))
}

func handleTest(w http.ResponseWriter, r *http.Request) {
	start := time.Now().UnixNano()

	// page1.htmlをパース
	tpl := template.Must(goingtpl.ParseFile("page1.html"))
	tpl.Execute(w, nil)

	fmt.Printf("ExecTime=%d MicroSec\n",
		(time.Now().UnixNano()-start)/int64(time.Microsecond))
}
```

実行結果はこんな感じ。
base.htmlの内容もパースされているのが分かると思います。
![extends.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272546/398ba748-a1c0-2942-f0bd-cda5339f1bb3.png)
MacにNode.jsをnodebrewでインストールして環境構築【決定版】

# <strong>Mac に Node.js を nodebrew でインストールして環境構築</strong>

Mac に Node.js をインストールする方法は複数ありますが、ここでは `nodebrew` によるインストールとバージョン管理方法を説明します。

<!-- 
    How to install Node.js
-->
## nodebrew の導入手順

`nodebrew` を `homebrew` でインストールします。

### homebrew のインストール

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

### nodebrew のインストール

```bash
brew install nodebrew
```

### nodebrew 有効化

以下のコマンドを実行し、 `nodebrew 1.0.1` と Usage などが表示されることを確認した上で、

```bash
nodebrew
```

以下のコマンドでセットアップを実行します。

```bash
nodebrew setup
```

### nodebrew の PATH を通す

setup が成功すると `export PATH=$HOME/.nodebrew/current/bin:$PATH` と PATH 指定が表示されます。

#### zsh を使用している場合

`zsh` を使用している場合は、 `.zshrc` に PATH を追加します。
_vim_ で `.zshrc` を開き

```zsh
vim ~/.zshrc
```

`i` を押してインサートモードにし、以下を貼り付けた上で `esc` を押してから `:wq` と入力してエンターを押し保存します。

```zsh
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

保存が完了したら _source_ で有効にしてください

```zsh
source ~/.zshrc
```

#### bash を使用している場合

`bash` を使用している場合は、 `.bash_profile` に PATH を追加します。
_vim_ で `.bash_profile` を開き上記と同様の手順で PATH 指定を書き加えて _source_ を実行してください。


<!-- 
    How to use nodebrew to install Node.js
-->

## nodebrew による Node.js のインストール

### インストール可能な Node.js のバージョン確認

インストール可能な Node.js のバージョン一覧を確認します

```bash
nodebrew ls-remote
```

### 指定したバージョンでインストール

上記で確認した一覧の中からインストールしたいバージョン名をコピーしてください。

```bash
nodebrew install v10.20.1
```

※ ここでは `v10.20.1` を例にインスールします。
※ インストール時にエラーが出た場合は[こちら](#%E8%A3%9C%E8%B6%B3)をご確認ください。

### インストールしたバージョンを有効にする

以下のコマンドでインストールしたバージョンの Node.js を有効にする

```bash
nodebrew use v10.20.1
```

### 有効になった Node.js の確認

以下を実行し、 `v10.20.1` と表示されればインストールの成功です。

```bash
node -V
```

### バージョンの切替

Node.js のバージョンを切り替えたい場合は、切り替えたいバージョンを _install_ した上で、 _use_ で指定することで切り替えが可能です。


<!-- 
    summary
-->
## まとめ

Node.js を `nodebrew` でバージョン指定しインストールする方法の説明でした。

---

## 補足

**`nodebrew install` でエラーが出た場合**

`nodebrew install` にて、 以下のような`No such file or directory` とエラーが出た場合、

```bash
Warning: Failed to create the file
Warning: : No such file or directory
```

`.nodebrew/src` ディレクトリを以下の手順で作成してあげることで対応可能です。

```bash
mkdir ~/.nodebrew
mkdir ~/.nodebrew/src
```
PythonでABC167のA~Cを解く

### はじめに
A~Cの三完でした。

### A問題
[問題](https://atcoder.jp/contests/abc167/tasks/abc167_a)

**考えたこと**
比較するだけ

```python
s = input()
t = input()

n = len(t)
if s == t[:n-1]:
    print('Yes')
else:
    print('No')
```

### B問題
[問題](https://atcoder.jp/contests/abc167/tasks/abc167_b)

**考えたこと**
致命的なtypoに気付かずに2WA()

```python
a, b, c, k = map(int,input().split())

if a >= k:  #k個全てa
    print(k)
elif a + b >= k: #cを取ると減るので、bから取る
    print(a)
else:
    n = k - (a + b)
    ans = a + -1 * n
    print(ans)
```

### C問題
[問題](https://atcoder.jp/contests/abc167/tasks/abc167_c)

**考えたこと**
Bで2WAして焦ってたので、提出するのが遅れてしまった。典型的なbit全探索、Nが十分に小さいの耐える。

```python
n, m, x = map(int,input().split())
ca = [list(map(int,input().split())) for _ in range(n)]

costs = []
for i in range(2 ** n):
    flag = True
    cost = 0
    algos = [0] * m
    op = [False] * n
    for j in range(n):
        if ((i >> j) & 1):
            op[n - j - 1] = True
    #print(op)
    for j in range(n):
        if op[j]:
            for k, u in enumerate(ca[j][1:]):
                algos[k] += u
            cost += ca[j][0]
    for j in algos:
        if j < x:
            flag = False
    if flag:
        costs.append(cost)

if len(costs) == 0:
    print(-1)
else:
    print(min(costs))
```

### D問題
[問題](https://atcoder.jp/contests/abc167/tasks/abc167_d)

**考えたこと**
ループ見つけて余りを求めてごにょごにょしてたけど8個くらいのケースで通らずにWA。

### まとめ
ここ3回のABCは毎回A,BでWA出してるので落ち着いて解けるようにしないといけない。ではまた、おやすみなさい。
【メソッド集】　rails  メソッド　まとめ　基礎　随時追加

#メソッド　まとめ　随時更新
参考：https://diveintocode.jp/blogs/Technology/RailsMethod01
参考：https://diveintocode.jp/blogs/Technology/RailsMethod01


##new
```
hoge.new # DBへ新たにインスタンスを追加
```
##save
```
hoge.save #　DBへ入力値を保存
```
##all
```
hoge.all #DBから関連モデルのデータを全て取得
```
##find
```
hoge.find(条件) # DBから条件を見つける
```
##destroy
```
@book.destroy #DBの指定のデータを消去
```
##where
```
hoge.where（条件） # DBから条件全てを取得
```
##order
```
hoge.order(カラム　条件) #条件に従ってカラムの順番を並び替え
```
##count
```
hoge.count #hogeの数を数える
```

##each
```
<%= @books.each do |book| %> # 配列でDBからデータを取得
```

##sort
```
hoge.sort #　数字：小→大、文字：アルファベット順、並び替え
```

##present?
```
@book.user.name.present?  #クラスに指定したものが存在していればtrue,そうでなければfalseを返す
```
##blank　※present?の対義語
```
@book.user.name.blank? #クラスに指定したものが存在していればfalse,そうでなければtrueを返す
```

##try
```
#nil の場合nilを返す。そうでない場合は、引数を実行
```

##now
```
now = DateTime.current #現在の日時を表示 
```

```
now.yesterday #昨日の日時を表示 
```

##order
```
@book.all.order(name::desc) # 降順に表示
```
※asc:昇順/desc:降順

##まとめ
たくさんあるのでメモ程度に追加していきます
【開発ログ⑤】見たことないエラーでビューが表示されなかった話

# 前提について
はじめまして、 プログラミングスクールに通ういりふねと申します。この記事は、スクールの課題である個人アプリの開発の記録を書くことで、自身のアウトプットに利用しています。もし、読んでいただけた方がいましたら、フィードバックをしていただけたら嬉しいです。

開発するのは「有給休暇管理ツール」です。仕様は[過去記事](https://qiita.com/iczo32/items/97ad7d4baa985b3b99ca)をどうぞ。

アプリはデプロイまで行いますが、サービスとして提供するものではありません。あくまでも自学習の一環ですので、ご理解下さい。では本題へどうぞ。

# 今回実施する内容
前回までで、テーブルの作成までが完了しました。今回は、「index,html.haml」のビューページの表示までを目指します。手順は次の通りです。
- ルーティングファイルを編集
- branchコントローラーの作成と編集
- index.html.hamlの作成
- ローカルからrootパスへアクセス
- 表示されていればOK

# 最初は順調
ルーティングの編集、branchesコントローラーの作成とindexアクションの編集。viewsディレクリ内に「branches」ディレクトリを作成し、「index.html.haml」の作成までサクサク進みます。ローカルサーバーを起動し、「local:3000」へアクセスするとエラーが出てきました(泣)

# 見たことないエラー。。。
<img width="683" alt="スクリーンショット 2020-05-10 14.31.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/d84599db-ac71-314d-d763-a5a326d1c450.png">

>ExecJS::RuntimeError in Branches#index

調べたところ、RubyからJavaScriptを実行する「ExcJS」に関するエラーのようで、解決策も複数あるようです。読んだ記事は[こちら](http://yso15.hatenablog.com/entry/2015/03/21/225843)。

>ExecJSとは
>Rubyスクリプトからjavascriptコードを実行するための仕組み
>ExecJSがjavascriptエンジンを自動検索（=autodetect）する

# gemのインストールで解決
いくつかあった解決方法の中に「therubyracer」というgemをインストールすれば良いとあったので、実行しましたが、そもそもbundle installがうまく完了しません。
念のため、ルーティングやコントローラーの記述を確認しましたが、こちらは問題ないようです。

そんなとき、[こちら](https://note.com/konpyu/n/na213a14ad1e3)の記事に出会いました。

>前置きが長くなりましたが以下が本題。今週久しぶりに環境構築をした所、案の定>therubyracerで止まり、「はいはい、またキミね」という感じだったのだが、なんとtherubyracerの後継としてmini_racerが爆誕しており、Rails本家にもマージされていた。
>
>mini_racerはかなり新しいlibv8をハンドリングしている。試してみた所簡単にインストールが成功した。

私もmini_racerのgemをインストールしたところ、無事にビューページが表示されました。これで、一件落着です。

# 今日の積み上げ
- カリキュラムに載っていないエラーを見つけたら、用語の確認、原因の調査をおこなう。
- 検索する際は、記事の作成日もチェックする。
- 時間がかかっても自分で解決する癖をつける。
PCからクロスケーブルでRaspberryPiに直接接続

#ネットワークなしでRaspberryPiに接続するには？

RaspberryPiにPCから有線接続する際、普通はルータを介して
![rooterlan.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/54c61c77-f577-b182-08ee-bb2c9af119cf.png)
のように接続すると思います。
無線でも基本的にはルータを介すこととなります。

上記方法では外出先等ネットワークが使えない環境では接続できませんが、
そんなときはPCとRaspberryPiを直接つなぐ
**・クロスケーブル（有線）**
**・アドホック接続（無線）**
が役に立ちます。

今回は前者のクロスケーブルで、RaspberryPiにアクセスしてみます

#必要なもの
・RaspberryPi (本例ではRaspberryPi3 ModelB)
・イーサネットポートのあるPC (本例ではWindows10)
・クロスケーブル（Amazon等で数100円～で売っています）

#手順
**①クロスケーブルで機器同士を接続**
**②IPの固定化**

##①クロスケーブルで機器同士を接続
下の図のように、RaspberryPiとPCをクロスケーブルで接続します

![crosscable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/ce607245-1d72-90df-f754-e640f8a49d54.png)


##②IPの固定化##

###PC側のIP固定
Windows10では、
「コントーロールパネル」 → 「ネットワークとインターネット」 → 「ネットワークと共有センター」 → 「アダプターの設定の変更」 → 「イーサネット」を右クリック

出てきた下記画面で「インターネットプロトコルバージョン4」を選択し「プロパティ」をクリック
![IMG_20200507_203908.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/ccc4bb28-546e-1d3b-7803-7165926e5ac9.jpeg)

IP設定を入力
![IMG_20200507_195853.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610167/eddf4f18-edc4-23f1-f91a-936a1b7f02a5.jpeg)
・IPアドレス：固定したいIP
・サブネットマスク：255.255.255.0
・デフォルトゲートウェイ：IPアドレスの最後のみ「1」に変えたもの
・優先DNSサーバー：IPアドレスの最後のみ「1」に変えたもの

OKを押すとIPが固定化されます

###RaspberryPiのIP固定
下記コマンドでdhcpcd.confを編集

```
sudo nano /etc/dhcpcd.conf
```

ファイルの最後に、下記の記載を追記して保存
（固定したいIPアドレスを192.168.2.223とした場合）

```
interface eth0
static ip_address=192.168.2.223/24
static routers=192.168.2.1
static domain_name_servers=192.168.2.1
```

###Pingによる接続確認 (RaspberryPi → PC)
RaspberryPi側から下記コマンドを打ち、
PCのIP（192.168.2.222）にPing送信します

```
ping 192.168.2.222
```

下記のようにPing送信時間等が表示されれば成功です

```
PING 192.168.2.222 (192.168.2.222) 56(84) bytes of data.
64 bytes from 192.168.2.222: icmp_Seq=1 ttl=128 time=1.55ms
：
```

###Pingによる接続確認 (PC → RaspberryPi)
PC側からコマンドプロンプトで下記コマンドを打ち、
RaspberryPiのIP（192.168.2.223）にPing送信します

```
ping 192.168.2.223
```

下記のようにPing送信時間等が表示されれば成功です

```
192.168.2.223 に ping を送信しています 32 バイトのデータ:
192.168.2.223 からの応答: バイト数 =32 時間 = 1ms TTL=64
：
```


**以上で、クロスケーブルでの通信確立は完了です！**
あとは[こちら](https://qiita.com/c60evaporator/items/2384416f1122ae124f50)の記事のようにSSH接続する等、自由に接続をカスタマイズしてください！
MaterializeのMobile Collapse Buttonの導入手順について

##見た目
結構面白いので試してみてはいかがでしょうか。
###デフォルト状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634461/197e8c40-43cc-41be-7c68-fb0fbd4be702.png)
###サイトを縮小した時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634461/85cfdb28-ee3a-f5a9-b34b-cf75a524ba03.png)
###上記図の左側ハンバーガーをクリックすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634461/c12826d8-1346-8c6f-53fe-b7660b57fd85.png)



##Materialize公式からそのまま導入
```application.html.erb
  <body>
    <nav>
      <div class="nav-wrapper">
        <a href="#!" class="brand-logo">Logo</a>
        <a href="#" data-activates="mobile-demo" class="button-collapse"><i class="material-icons">menu</i></a>
        <ul class="right hide-on-med-and-down">
          <li><a href="sass.html">Sass</a></li>
          <li><a href="badges.html">Components</a></li>
          <li><a href="collapsible.html">Javascript</a></li>
          <li><a href="mobile.html">Mobile</a></li>
        </ul>
        <ul class="side-nav" id="mobile-demo">
          <li><a href="sass.html">Sass</a></li>
          <li><a href="badges.html">Components</a></li>
          <li><a href="collapsible.html">Javascript</a></li>
          <li><a href="mobile.html">Mobile</a></li>
        </ul>
      </div>
    </nav>
  </body>
```
##JSファイルでInitialization
```application.js
$( document ).ready(function(){
  $(".button-collapse").sideNav();
});
```

##万が一うまく表示されない場合
バージョンなどでjQuery関数がうまく動かない場合もありうるので、下記の追加を試してみるのも良い
参考元：　https://stackoverflow.com/questions/32486967/materializecss-mobile-collapse-menu-not-showing-when-clicked

```application.html.erb
  <head>
    <title>Portfolio</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
    <link href="https://code.jquery.com/mobile/1.4.5/jquery.mobile.structure-1.4.5.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/js/materialize.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.0/css/materialize.min.css" rel="stylesheet"/>
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  </head>
```
ActionSheet で width == - 16 の Auto Layout 警告が出た時の対処法

単純なレイアウトで `UIAlertController` の `actionSheet` を使ったときになぜか Auto Layout がうまく言ってないようだったのでメモ。

# 現象

ここでは例としてボタンをタップしたらアクションシートを表示するだけのコードを用意しました。

```swift
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func showActionSheet(_ sender: Any) {
        let alert = UIAlertController(title: "title", message: "message", preferredStyle: .actionSheet)
        let defaultAction = UIAlertAction(title: "item", style: .default, handler: nil)
        alert.addAction(defaultAction)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        alert.addAction(cancelAction)
        present(alert, animated: true, completion: nil)
    }
}
```

<img width="260" alt="IMG_2B79FE610AF4-1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/6659d96f-2f94-2a1c-edad-d8e18677ecbf.jpeg">

これを Xcode 11.4, iOS 13.3 の端末で実行すると、こんなログがだらだらと流れてきました。

```
2020-05-10 22:14:35.759481+0900 UIKitCustomCollection[53013:10180992] [LayoutConstraints] Unable to simultaneously satisfy constraints.
	Probably at least one of the constraints in the following list is one you don't want. 
	Try this: 
		(1) look at each constraint and try to figure out which you don't expect; 
		(2) find the code that added the unwanted constraint or constraints and fix it. 
(
    "<NSLayoutConstraint:0x2806e9720 UIView:0x103e0d040.width == - 16   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x2806e9720 UIView:0x103e0d040.width == - 16   (active)>

Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKitCore/UIView.h> may also be helpful.
(lldb) 
```

幅が16のコンテンツに覚えはないし `<NSLayoutConstraint:0x2806e9720 UIView:0x103e0d040.width == - 16   (active)>` と言われているので、ViewHierarchyで `0x103e0d040` を絞り込んでみたところ、UIAlertController の中の要素っぽいです。

![スクリーンショット 2020-05-10 22.16.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/1edd3150-012c-c380-fd69-c73a2b5d8c68.png)

# 原因

いろいろググってみたところ、iOS 12.2 から（少なくとも iOS 13.4 まで）存在している、OS 側のバグのようです。
Radarはこちら。
[Action sheet causes LayoutConstraints warning](http://openradar.appspot.com/49289931)

# 対処法

うまくいった対処法は以下の Stack Overflow の方法です。
https://stackoverflow.com/questions/55653187/swift-default-alertviewcontroller-breaking-constraints

```swift
extension UIAlertController {
    override open func viewDidLoad() {
        super.viewDidLoad()
        pruneNegativeWidthConstraints()
    }
    
    private func pruneNegativeWidthConstraints() {
        for subView in self.view.subviews {
            for constraint in subView.constraints where constraint.debugDescription.contains("width == - 16") {
                subView.removeConstraint(constraint)
            }
        }
    }
}
```

本当に今回のバグで発生した `width == - 16` だけを remove してるのか少し不安なところですが、おそらくこれ以外の原因では `width == - 16` 警告は発生しないのでは…。

# おまけ

`animeted` を `false` にすると解決するという情報もありましたが、私には効果がありませんでした。
ProcessingでVJ素材を作るブログ　第六回 動画として出力する

[第四回](https://qiita.com/naoya_vj/items/492bfce00f91d3c61965)でロード中の動画を作ったが、せっかくなので動画ファイルとして出力しよう。
動画作成する前に、pdeファイルを名前をつけて保存しておこう。
出力は簡単で最後に「saveFrame("frames/######.tif");」を入れれば良い。

※png形式でもいいようです。容量の節約を考えるのならpngかな。

出力すると、プロジェクトフォルダにtifファイルがたくさん入ったフォルダが作成される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632724/f9c0efb8-e83f-fe89-7217-7debf56250fd.png)

あとはProcessing開いて上部の「ツール」→「ムービーメーカー」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632724/a74a5e81-f631-aded-fa21-69055ba80d21.png)

「frames」フォルダを指定して「動画を作成」を選択すれば、プロジェクトフォルダの１つ上の階層にできますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632724/0102429a-aecd-43ec-34e4-c56409e5261a.png)


VJと方々が使っていると噂のVDMX5とうまいこと連携できたらいいですなぁ。

ではでは
【オブジェクト指向】ゼロをイチにする備忘録【概念の理解に役立ったサイトまとめ】

##はじめに
文系・未経験の人間がゼロをイチにするために学んだことをまとめています。
特にここではJavaを勉強し始めて1週間の赤ちゃん状態の人間が読んでも理解できた、すっごいサイトばかりをまとめました。

おそらくここにたどり着くような方にはわかってもらえると思うんですが、初心者用のサイトを見てもまずワードがわからん。カタカナを直訳しても概念が理解できん。
逆にすっごくかみ砕いた表現だと、話の内容とプログラミングが結びつかずに結局何にもなってない。

詰む。

という地獄を体験するんですよね。
ここに集めたものはその地獄から救ってくれたメシアサイトばかりなのでめちゃくちゃお役立ちだと思っています。随時追加予定。
一応四則演算やループ処理、while文といった内容は理解した状態だと思ってください。

##オブジェクト指向プログラミングとはなんぞや

+ [OOPと非OOPの違い｜オブジェクト指向プログラミングをおさらいしよう（１）](https://www.gixo.jp/blog/4735/)
+ [継承によってコードを再利用する｜オブジェクト指向プログラミングをおさらいしよう（２）](https://www.gixo.jp/blog/5016/)
+ [インターフェースとは？～継承とは役割が違う～｜オブジェクト指向プログラミングをおさらいしよう（３）](https://www.gixo.jp/blog/5159/)
+ [カプセル化とは？～安全なシステムを作る為の配慮～｜オブジェクト指向プログラミングをおさらいしよう（４）](https://www.gixo.jp/blog/5914/)
+ [静的型付けと動的型付け～JavaとJavascriptのJSON処理を比較～｜オブジェクト指向プログラミングをおさらいしよう（５）](https://www.gixo.jp/blog/5963/)
+ [ポリモルフィズムとインターフェース～クラスは違えど同じ目的には同じメソッド名を～｜オブジェクト指向プログラミングをおさらいしよう（６）](https://www.gixo.jp/blog/6135/)

特に最後のポリモルフィズム（ポリモーフィズム）についての記事は必見。これを読む前と読んだ後では見える世界が違う。
django ユニットテストでエラー

こんなエラー

```
django.db.utils.OperationalError: (1366, "Incorrect string value: '\\xE3\\x83\\xA6\\xE3\\x83\\xBC...' for column `test_hoge`.`auth_permission`.`name` at row 1")
```

database(ここではmariadb)の文字コードがおかしいらしい

https://qiita.com/niceland/items/f35fa240f739ff70b85e
mariadb デフォルト文字コード変更


##※ centos7の場合

/etc/my.cnf.d/server.cnf

```
[mysqld]
...
character-set-server=utf8mb4

[client]
default-character-set=utf8mb4
```

```
MariaDB [(none)]> show variables like "chara%";
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8mb4                    |
| character_set_connection | utf8mb4                    |
| character_set_database   | utf8mb4                    |
| character_set_filesystem | binary                     |
| character_set_results    | utf8mb4                    |
| character_set_server     | utf8mb4                    |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.001 sec)
```

character_set_systemは常にutf8になるとのこと
pth(pytorch)をonnxに変換するのは簡単か?　OpenVINOのIR(Intermediate Representation)に（も）関連した記事。

#目的
この記事は、下名のような、いくつかわかってないことがある人向けです。非常に詳しい人は、読む意味がないと思います。

人それぞれ目的は、違うと思いますが、ワタシは、OpenVINOのIRファイルを作りたくて、かつ、そのもともとの情報が、Pytorchであるケースがありました。
そのため、その変換に挑戦しました。

OpenVINOによると、Pytorchは、直接は扱えず、ONNXを経由する必要があることのこと。

よって、

**pthをonnxに変換する**

ことを検討しました。
例えば、
**AAA_BBB.pthというファイルをどこかからもってきて**
Pythonを使うとして、期待するのは、以下のような感じでしょうか。

```
python convert.py -i AAA_BBB.pth -o AAA_BBB.onnx
```
こんな感じではできない気がしています、今。

#説明

##簡単じゃない説明
そもそも、
**AAA_BBB.pthというファイルをどこかからもってきて**
という前提の場合は、
下記では、情報が足りないんではないでしょうか？
たぶん、pthだけでは、足らないのでは？（＜－－このあたりが極端に不勉強ですが。）

```
python convert.py -i AAA_BBB.pth -o AAA_BBB.onnx
```

##では、どうすればいいのか。1
以下など参考になるのではないでしょうか？
モデルの情報がある感じで、
かつ、torchの環境で
**torch.onnx.export()**等で出力する。
これだとできるような気がします。
⇒すみません、これは、自分では試していません。

https://michhar.github.io/convert-pytorch-onnx/

```
import torch
import torch.onnx

# A model class instance (class not shown)
model = MyModelClass()

# Load the weights from a file (.pth usually)
state_dict = torch.load(weights_path)

# Load the weights now into a model net architecture defined by our class
model.load_state_dict(state_dict)

# Create the right input shape (e.g. for an image)
dummy_input = torch.randn(sample_batch_size, channel, height, width)

torch.onnx.export(model, dummy_input, "onnx_model_name.onnx")

```

##では、どうすればいいのか。2

https://qiita.com/PINTO/items/e1bf5ef24ed6ad6f6a05
も、参考になると思います。

**ただ、これの場合は、human-pose-estimation-3d-0001.pthの情報だけで、変換しているわけではない、ハズです。**
（いろいろ、モデルの情報がある前提。たぶん、このあたりは、非常に当たり前のことなんだと思いますが。）

⇒実際にやってみました。できました。（というかいきなりIRファイルまでできましたので、、、んんん。）

#まとめ
「pth(pytorch)をonnxに変換するのは簡単か?」は、**あんまり、状況がよくわかってない人には、簡単でない**という記事でした。ワタシのようなレベル、完全な素人ではないが、あまり、しっかり全体を理解していない人には、の前提付きです。

⇒OpenVINOの説明がよくわからないので、記事にしたという面もあります。

コメントなどあれば、お願いします。
[はてなブログ] コンテンツエリアだけリンクを別ウィンドウ表示

いちいち「html編集」モードでAタグに target="_blank" を挿入するのは大変です。でも、外部ドメインへのリンクは別ウィンドウにしたいですよね。そんなときは、

設定 > 詳細設定 > 検索エンジン最適化 > "headに要素を追加"

入力箇所はここです↓
![link.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159452/b0d68ef4-79d6-3f9f-8b86-cffc224e7a4f.png)

に以下を設定してみましょう。


```javascript:
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha256-4+XzXVhsDmqanXGHaHvgh1gMQKX40OUvDEBTu8JcmNs=" crossorigin="anonymous"></script>
<script>
jQuery(document).ready(function(){
    $(".entry-content").find("a").attr("target", "_blank");
});
</script>
```

これでentry-contentクラスの配下のリンクは全て別ウィンドウに遷移するはずです。
お試しあれ。

この方法の他に、

```html:
<base target="_blank">
```

と設定してbaseを変更する方法もありますが、これだとメインタイトルをクリックしても、関連記事のリンクをクリックしてもどんどんWindowが量産されてしまうので、ちょっとユーザビリティ的によくないですね。
【開発ログ④】順番が違うマイグレーションでつまずいた話

# 前提について
はじめまして、 プログラミングスクールに通ういりふねと申します。この記事は、スクールの課題である個人アプリの開発の記録を書くことで、自身のアウトプットに利用しています。もし、読んでいただけた方がいましたら、フィードバックをしていただけたら嬉しいです。

開発するのは「有給休暇管理ツール」です。仕様は[過去記事](https://qiita.com/iczo32/items/97ad7d4baa985b3b99ca)をどうぞ。

アプリはデプロイまで行いますが、サービスとして提供するものではありません。あくまでも自学習の一環ですので、ご理解下さい。では本題へどうぞ。

# 今回実施する内容
昨日までで、Railsで新規アプリケーションの作成、データベースの作成までは完了しました。ローカルサーバーを起動し、「localhost:3000」にアクセスしてRailsのトップ画面の表示まではなんとかできているというところからスタートです。

今回の実施内容は以下のとおりです。
- モデルファイルの作成
- deviseの導入
- マイグレーションファイルの編集と実行
- 問題なくテーブルができたらOK

# エラー発生!! user_idがない!?
モデルファイルの作成、マイグレーションファイルの編集、マイグレーションの実行とほぼカリキュラムで習った内容をそのまま実施したつもりでしたが、出来上がったテーブルを見てうまく作成できていないことに気が付きました。

Branchテーブルとholidayテーブルに「user_id」のカラム表示されていないのです。この「user_id」は、Gemのdeviseで作成したuserテーブルを紐付けるためのものです。何度かロールバックしてマイグレーションファイルの編集を行ったり、再度マイグレーションを実行しても一向に変化がありませんでした。

ターミナルの内容を見ると、userテーブルがないので、user_idを外部キーとして設定できないというエラーを見つけました。いやいや、userテーブルを作るマイグレーションファイルあるじゃん。１時間位、エラー文と格闘していました。

# 解決!! マイグレーションは作成順に実行される
最終的にRailsガイドの[こちら](https://railsguides.jp/active_record_migrations.html)の記事を見て、原因が分かりました。私が、先にモデルファイルを作成し、その後でgemのdeviseを実行してマイグレーションファイルを生成していたのです。

>Railsではマイグレーションの実行順序をファイル名のタイムスタンプで決定します。従って、マイグレーションを他のアプリケーションからコピーしたり、自分でマイグレーションを生成する場合は、実行順に注意する必要があります。
>Railsガイドより抜粋

つまり、最後にインストールしたdeviseのマイグレーションファイルが、タイムスタンプにより最後に実行されるため、それより前に実行している「branch」や「holiday」のマイグレーションファイルに「user_id」とカラムを設定していても、そんなテーブルはない。ということになっていたようです。

# 簡単に解決しようとしたら!
以上の理由であれば、ファイル名を変更すれば良いのではないか？と思い、deviseから生成されたマイグレーションファイルのタイムスタンプを早い時間に書き換えました。マイグレーションをすると、再度エラー!!

ファイル名を変えたことで、変更前のマイグレーションファイルと競合を起こしているようでした。変更前のマイグレーションファイルがどうしてもロールバックできなくなり、あえなく失敗。

# 手順を変えて作りなおし
結局、また１時間くらい格闘しましたが、私の力ではリカバーすることができず。
再度新規アプリケーションを立ち上げて、deviseのインストールから実行することで、うまくデータベースが作成できました。ミスのリカバーまでできたら最高でしたが、開発の初期段階だったので、修正が効きました。
<img width="850" alt="スクリーンショット 2020-05-10 22.05.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/2a89bef1-361d-2403-1645-8830d0119eb1.png">

写真は、branchテーブルです。user_idがでました。
<img width="529" alt="スクリーンショット 2020-05-10 22.06.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614723/91dda996-c700-5a02-7125-cd3af429fbff.png">


# 今日の積み上げ
- 各モデルファイルの作成前に、gem'devise'のインストールを終わらせておく。
- もし、エラーが出ても焦らず、エラー文を丁寧に読む。
- カリキュラムで手慣れていると思った工程でも、必ず手順や実施方法を確認しながら行う。
CSS 基礎・基本 CCS3 #13

今回学習していくcss3は従来のcssに比べてより多彩な装飾が可能になったものです。今までのcssを一通り前回までのを見てからやるとよいと思います。学習ノート進めてゆく！

##より多彩な要素の選択方法！

###特定の文字から始まる要素の選択！
`sample`という文字から始まるクラス、を持つ要素に対して装飾を加えたい場合、`^=`を入れることで「・・・から始まる」にできる。
`li[class^="sample"] {  }`

###特定の文字で終わる要素の選択！
`$=`「・・・でおわる」ものを先とは逆で行う。
`li[class$="sample"] { background-color: #6C6 }`

###ある要素の中で最初の要素の選択
div要素の中で最初に含まれるp要素の選択などの場合に使う。
`:first-child`疑似クラスを用いて行う。
`p:first-child{ }` 

###ある要素の中で最後の要素の選択
div要素の中で最後に含まれるp要素の選択などの場合に使う。
`:last-child`疑似クラスを用いて行う。
`p:last-child{ }`

###ある要素の中でn番目の要素の選択
ある要素の中で二番名に現れるp要素を選択する場合は、`nth-child()`を使って書くことができる。
`p:nth-child(2) {  }`

###ある要素の中にある、最初の特定要素の選択
先ほど出てきたのと似たようですが、今回は最初の特定！の要素です。`first-child`はすべての要素を順番に入れて数えているが、`first-of-type`は特定の要素に絞って数えていく。
`p:first-of-type{  }`

###ある要素の中にある、最初の特定要素の選択
上のを逆にしたものです。
`p:last-of-type{  }`

###ある要素の中にある、n個目の特定の要素の選択
これも、特定化された感じなだけです。
`p:nth-of-type(2){  }`

##色の透過！

###opacityによる色の透過
`opacity`の値を0~1で扱うことで透過が変化します。値が大きいほど不透明になります。
`div{ pacity: 1.0;}`

###rgbaによる色の透過
rgba要素は色と透明度決める。red,green,blueと透明度の指定になります。
`div { background: rgba(207,207,0,0.2);}`

##影！

###要素の影 1
ある要素に影をつけるには`box-shadow`使います。`box-shadow: x座標 y座標 ぼかし 色;`
x座標の値を大きくすればするほど、影は右にいく、小さくすればその逆になる
y座標の値が大きくなればなるほど影は下に行き、小さくなればなるほど逆に行く。

###要素の内側の影
`box-shadow: x座標 y座標 ぼかし 色 inset;`
insetを使うと内側に影を作れる。

###テキストの影
今回は`text-shadow`を使用して影をつけていきます。
`text-shadow: 0 0 10px #F00`
設定の仕方は先ほどのと同様です。

##枠線を丸める！

###枠線を作る
`border: 3px solid #000;`

###枠線を丸める！
枠線を丸めるには`border-radiusを使う！
`border-radius: 半径;`

###はみ出した文字を削除
枠線を丸くしていくと円状になったりします。そうするともともと四角形だったためにはみ出すところが出てきます。
はみ出した要素を`overflow`属性を使用し値をhiddenを指定します。
`overflow: hidden;`

###線形グラデーション
線形グラデーションを使用するには、`linear-gradient`という属性を使用します。
`linear-gradient(最初の色、後の色);

###円形グラデーション！
円形グラデーションには`radial-gradient(内側の色、外側の色);

###マウスオーバーによる横幅と縦幅の変化！
`div:hover{ height: 200px; width: 200px;}`を使うことでマウスカーソルをある要素に乗せたときにスタイル指定できる。

###横幅の滑らかな変化！
横幅を一定の速さで変化させる場合、transitionを使用して滑らかにする。`linear`はタイムんぐ関数の一つで、時間に対してどれだけ変化するかを決める。
`transition: width linear 秒数(s);`

###縦幅の滑らかな変化！
このように、heightに変えるだけ。
`transition: height linear 秒数(s);`

###背景色の滑らかな変化！
背景色も、background-colorを使う。
transition: background-color linear 秒数(s);

###すべての属性の滑らかな変化
すべての場合は、`all`を使う。
transition: all linear 秒数(s);

###変化のさせ方を変更！
transtion属性の値にlinearを使っていましたがそのほかを紹介します。
- linear 速度は変わらない
- ease ゆっくり始まりゆっくり終わる
- ease-in ゆっくり始まる
- ease-out ゆっくり終わる

##アニメーションを作る！

###キーフレームを作成
`@keyframes`のアニメーションの一連の流れをまとめたもので以下のように定義します。
`@keyframes mover { }`

###一番最初の状態を設定！
アニメーションは0%~100%世言う範囲で指定する。
0%がアニメーションの最初の状態、100%がアニメーションの最後の状態。また、範囲内なら任意の部分にいくつでもスタイルを設定できる。
`@keyframes mover { 0% background-color: #000; }`

###一番最後の状態を設定！
`@keyframes mover { 100% background-color: #FFF; }`

###アニメーションをつける
ある要素に作成したアニメーションを指定する場合は、その要素に対して`animation`を適用する。
`animation: mover linear 1.0s 3;`

###永遠にアニメーションをつける！
永遠にするには、`infinite`を使う！
`animation: mover linear 1.0s infinite;`

###アニメーションを逆転する！
`alternate`を使って100%-0%の順でも動くようにする。
`animation: mover linear 1.0s infinite alternate;`

---

今回は、アニメーションなど今どきのモダンな設計を作るにはなかなか便利な機能ばかりでした。あと数回でwebテクノロジーの勉強ノートも終わりそうです。
Railsで新規にアプリを作成する

#手順

ターミナルにて

```
$ rails バージョン　new アプリケーション名 -オプション名
```

で新規アプリを作成することができます

バージョンはアプリケーションをRailsのどのバージョンを用いて作成するのかを指定します。

オプションはハイフンの後に、指定することで様々なオプションをつけることが出来ます。

仮に、Railsのバージョンは5.2.3、データベースをMySQLに指定して新規アプリを作成する場合

```
$ rails _5._2._3_　new アプリケーション名 -d mysql
```

となります。

オプションの種類は様々ですので調べてみて下さい。


これで新規アプリケーションは作成できましたが、データを蓄積するにはデータベースが必要です。


[webアプリケーションの仕組みはこちら](https://qiita.com/kouhei_matuura/items/ff6e86e80379deb864cf)

#データベースの作成


webアプリケーションはクライアント（今使っているPCなど）とサーバー（アプリケーションとデータベース）をインターネットを介して情報を送ったり受け取ったりしています。

そのため、アプリケーションを制作しただけではデータの蓄積ができません。

```
$ rails db:create
```

「rails new」　でアプリを作成したら、上記のコマンドを打ってデータベースもセットで作成しましょう
PHPの例で学ぶインターフェイスって何？

現場でPHPのコードを見る中で、インターフェイスが実装されているケースがあるのですが、初心者に毛が生えたレベルのエンジニアの私には、よく分かっていないので、まとめてみました。

まずは公式よりの引用↓

0.公式よりの引用
> 
>オブジェクトインターフェイスにより、あるクラスが実装する必要があるメソッドの 種類を、これらのメソッドの実装を定義することなく、指定するコードを作成できる ようになります。
>
インターフェイスは通常のクラスと同様に定義することができますが、 キーワード class のかわりに interface を用います。またメソッドの実装は全く定義されません。
>
インターフェイス内で宣言される全てのメソッドはpublicである必要があります。 これは、インターフェイスの特性によります。
>
コンストラクタ をインターフェイスで宣言できることに注意して下さい。 これはたとえばファクトリで使う場合など、コンテクストによっては役に立ちます。
> 

[公式より引用] (https://www.php.net/manual/ja/language.oop5.interfaces.php)

、、、
公式のみだと分かりにくいので、下記で、実装方法の要点をまとめた。

1.インターフェイスの実装方法要点
・classと同じようなかたちで記述できるが、interface XXX(interface名)で記述をする。
・インターフェイスの中ではメソッドの中身は実装されない。
・インターフェイスで実装されるメソッドはpublicである必要がある。
・インターフェイスを実装したクラスは、必ずその定義されたメソッドを使用しなければならない**（重要）**

2.インターフェース記述例
ここでは、インターフェイス「behavior」を定義し、クラス「man」に実装(インプリメント)した。


```sample.php

<?php

// Your code here!
interface behavior
{
  //インターフェイスでは、実装することができない。
  public function eat();
  public function sleep();
  public function walk();
}
          
class man implements behavior
{
  public function eat()
  {
      echo "食べる";
  }
  public function sleep()
  {
      echo "寝る";
  }
  public function walk()
  {
      echo "歩く";
  }
}

$sato = new man();
$sato->eat();
  
?>

>>出力結果
食べる
  
```

3.何故インターフェイスを使うのか
インターフェースがなくても、クラスだけでeat,sleep,walkのメソッドは使用できるが、何故インターフェースを使用するのか。
メリットととしては下記があげられる。

・インターフェイスがあれば、実装先クラスの機能を把握しやすくなる
・インターフェイスで実装されたメソッドは、その実装先のクラスで記述されなければ、エラーになるので、必要なメソッドの実装漏れを防げる
なぜpythonでimportするとモジュールが使えるのか

ちょっと気になっていて調べたらなるほどとなったのでメモ

皆さん何気なく使っているimport文。
pipでインストールしたモジュールを使うために、pythonを勉強し始めたときに、きっと誰もが一度は使ったと思います。

```
import os
import math
import cv2
...
```

## 自分で書いたクラス、関数を呼び出したい

ある程度、pythonが書けるようになってくると、自分で書いたコードを分割したりして、管理したいと思うはずです。
例えば、util_func.pyという関数をたくさん定義したファイルを作っておいて、ほかのスクリプトでも使えるようにするみたいな感じです。

その時に、何の考えもなしに

```
from util_func import f1
```
みたいな感じに書くと、Module not foundというエラーが出たこと、皆さんありませんか？

そこで調べてみると、以下の様なコードを挿入すると大丈夫らしい。

```
sys.path.append(os.pardir) #ファイル構成にもよりますが。。。
```

実際にやってみると、ちゃんとできてる。。。。

## この1行のスクリプトが何をやっているか
前置きが長くなりましたが、本題です。
この1行のスクリプトが何をやっているかを簡単に説明します。

まず、sys.pathをprintで出力してみます。

```
import sys
print(sys.path)
```
すると以下の様なリストが返ってきます。

```
[ '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages', '~/.local/lib/python3.6/site-packages/IPython/extensions', '~/.ipython', '..']
```

これはpythonが読み込み可能なpathを示しています。

つまり、今まで自作関数やクラスをほかのファイルからimportしたときに、"module not found"と怒られていたのは、`sys.path`にそのスクリプトのpathが存在していなかったからなのです。

よって、`append`メソッドを使用して、リストにpathの情報を加えてあげると、見事自作のスクリプトを呼び出すことができるというわけです。
Teams会議を開くハードルをとにかく下げたい

## Teams会議を設定するのがめんどくさい

自分の会社でリモート会議を行うときはMicrosoft Teamsを使っているのですが、Teams会議を開くのがめんどくさい。

予定表に予め設定してあれば、「予定表」タブから参加をクリックすればいいのですが、気軽に「ちょっと話そうよ」というときにハードルが高いです。
予定表からTeams会議を登録するのもめんどくさいですし、人を追加したいというときもめんどくさい。

ので、どうにかハードルを下げる方法がないかを考えてみました。

## Teams会議へのリンクを全員で共有しておく

実は、Teams会議には招待用リンクを作成する機能があります。
以下の手順でリンクを作成しておき、全員で共有しておきます。

- 会議に参加する
- 参加者を表示
- 他のユーザーを招待の右に(参加情報をコピー)というボタンがあるのでクリック
- これでクリップボードにリンクが取得されているはずです。

そうすれば「会議室①に集合」だけ言えば同じリンクを叩いて集合できます。
Slack等にリンクを貼っておけばさらに便利になります。

これで、ぱっと集まりたいときにも以下の手順でTeams会議に全員が集まれるようになりました。

- Slackでリンクを叩く
- ブラウザが立ち上がり、「Teamsを開く」をクリックする
- Teamsが立ち上がり、「会議に参加する」をクリックする

## 謎のブラウザ経由をなくしたい

Slackから直接Teamsが立ち上がればいいのですが、謎にブラウザ経由するのがまだストレスでハードルが高いです。
どうやら、Teams内で完結させれば謎のブラウザ経由をしなくて済むみたいです。

ここで、「Wiki」という機能を使ってみました。
TeamsのWikiにリンクを貼っておけばそのままTeams会議に参加できます。

- 会議室①
    - リンク
- 会議室②
    - リンク
  
のようなWikiのページを作成しました。
これで、チーム全員がWikiのタブにいってクリックすればTeams会議に集まれるようになりました。

## さらにもう一工夫

Wikiのタブに移動するのがめんどくさかったのでどうにか解消できないか考えてみました。
(ちょっといまいちですが、)Microsoft Teamsの左側のタブに「Wiki」を追加してピン留めする方法で少しマシになりました。

これでCtrl + 7とかでWikiのページが開きます。
→デフォルトで表示されるのが個人Wikiのページなので、各リンクを個人Wikiに貼っておけば、以下手順でTeams会議に参加できます。

- 「Ctrl + 7」でWikiのタブを開く
- リンクをクリックする
- 「会議に参加する」をクリックする


----

自分はこのあたりが限界でした。
もう少し楽に会議室①とかに参加する方法があればいいんですけどね、、

Teamsを開いた状態で「Ctrl+Shift+1」で会議室に参加するくらいまで持っていければよかったのですが、自分が発見できたのは以上でした。。

最後まで読んでいただきありがとうございました！