OmniAICreator/Qiita-1.07M huggingface dataset:
日頃心掛けたいシェルスクリプトの治安維持

気が向いたので、久しぶりに執筆してみました。

最近、とある案件で初めてそこそこ本格的にシェルスクリプトを書いたのですが、今までバッチしか知らなかった僕からして見たら「なにこれOS付属のくせにガチのプログラミング言語じゃん！」となり、ちょっとしたマイブームが来ています!

そこで色々と感じたことをメモっていきます。

# 治安維持は必要
シェルスクリプトはかなり万能ですが、他のプログラミング言語と比較して曖昧な表記でも許されてしまう、という点は場合によって諸刃の剣だと感じました。

つまり、自分である程度の自治をしないと、後で見返したときに苦労することになる、ということです。

# 施策
## 初期設定
```sh:Example
set -uC ignoreeof
```

`set`は、コンテキスト内でのスクリプトエンジンの挙動を設定/確認するコマンドです。

サンプルに記載されているオプションは次の通りです。

### `-u`
いわゆる厳格モードす。
未宣言の変数を使用禁止にします。

### `-C`
リダイレクト(`>`)でのファイルの上書きを禁止します。
なお、追記`>>`はOKです。

ファイルを上書きする場合は`rm && touch`のように、処理を明示的に記述します。

### `ignoreeof`
`Ctrl+D`が入力されてもスクリプトが終了しないようにします。

### その他
他にも、コマンド終了コードが0以外(異常終了)なら即座にスクリプトを中断する`-e`オプションや、標準エラー出力を表示する`-x`オプションなどありますが、いずれも必要な場合とそうでない場合があると思いますので、サンプルには記載しませんでした。

なお、これらの設定はシェルスクリプトの1行目に`#!/bin/bash`のような記述をする、いわゆる "shebang" でも同様に行えます。

しかし、これは個人的な意見ですが、コメント部分に実行されるコードが存在するって何か気持ち悪くありませんか...?

なのでshebangは使用せず`set`コマンドを使用したほうが良いと考えます。

## 変数
```sh:Example
declare -r foo="bar"

for _path in "/path/to/*"
do
    echo ${_path}
done
unset _path

read _hoge
declare -r hoge="/path/to/${_hoge}"
unset _hoge
```

### 宣言
シェルスクリプトは、他言語での`var`のような変数宣言句なしに唐突に変数宣言できますが、ちゃんと`declare`という変数宣言コマンドが存在します。

`declare`は非常に優秀で、関数内で宣言すれば自動的にローカルスコープになりますし、定数は`-r`オプションを付与すれば読み取り専用(`readonly`コマンド相当)になります。

他にも`-a`オプションで配列を宣言できたりと、使わない手はありません。

なにより`declare`で明示的に変数宣言することにより、これは変数だと判別しやすくなります。

どんな変数でも、宣言する際は`declare`コマンドで宣言しましょう。

また、他言語と同様に上書き可能な変数はなるべく減らし、できるだけ定数(`-r`)として宣言するよう心がけましょう。

### 解放
`read`や`for`といったコマンドで宣言する局所的変数は、入力バリデーションやループが終了したら使わなくなるケースがほとんどです。

特に注意したいのが`for`の変数で、ループ内でしか使用しないにもかかわらずグローバルスコープとなっており、変数名を使い回そうとすると多重定義となり、次回使用時まで不要なデータが残ってしまいます。

なので、ループが終了したら必ず`unset`で解放しましょう。
`read`も同様に、バリデーションなどの処理が完了したら`declare`で宣言した変数(定数)に移し替えましょう。

### 呼出
シェルスクリプトは変数名に`$`を付与して変数を呼び出せますが、更にブレースで囲う記法(`${}`)も用意されています。

詳細は割愛しますが、シェルスクリプトのブレースには他にも様々な機能があり、そのうちブレースの前に`$`を付与したものが変数呼出の機能、ということです。

ブレース変数呼出には、変数名の前に`#`を付与することで文字数を調べられたり、変数名の後に`#`を付与することで内容を展開できたり、かなり高度な処理を簡単に行えます。

何より、いきなり`$foo`が現れるより`${foo}`のほうが読みやすいと思います。

なので、変数呼出は必ずブレース記法を使用するようにしましょう。

## 文字列
```sh:Example
echo "hogefuga"
```

### ダブルクォーテーション
シェルスクリプトは、特に何も囲わずベタ書きすれば全て文字列の扱いになりますが、他言語と同様にダブルクォーテーションで囲う記法(`""`)も存在します。

昔ながらのダブルクォーテーションの用途といえば、文字列内に空白が存在する場合に用いられてきました。

しかし、もちろん空白なんて存在しなくても使用して問題ありません。
それどころか、積極的に使用すべきです。

これは特に見やすさの面で関わってくると思いますが、ダブルクォーテーションで囲うとエディタのシンタックスハイライトが効き、圧倒的に読みやすくなります。

なので、文字列は必ずダブルクォーテーションで囲うようにしましょう。

# まとめ
自治しながら書いていけば、かなり有用な言語だと思いました。
OSと密接なので、そういう操作をする場合は重宝するかと思います。

しかし、治安維持をサボり続けるとそこは魔境に...

今後、他にも治安維持に役立てそうな知見を得たら追記していきます!!
結合されていないメッシュの頂点座標を左右対称にする

結合されているメッシュは、メッシュの編集→シンメトリや反転で左右入れ替えできるが
結合されていないメッシュは、メッシュの編集→シンメトリや反転が使えないので
以下のようなMELを作った。他にも何か標準機能でのやり方があるかもしれないけど…。

右と左のオブジェクトを選択して実行

```c
global proc vertexL_to_vertexR()
{
   string $sl[] = `ls -sl`;
    string $ver1[] = `polyListComponentConversion -toVertex $sl[0]`;
    string $ver1E[] = `filterExpand -selectionMask 31 $ver1`;
    
    string $ver2[] = `polyListComponentConversion -toVertex $sl[1]`;
    string $ver2E[] = `filterExpand -selectionMask 31 $ver2`;
    //print($ver2E);
    
    int $i = 0;
    for($obj in $ver1E)
    {
        float $pos[] = `xform -q -ws -t $obj`;
        xform -ws -t (-1*$pos[0]) $pos[1] $pos[2] $ver2E[$i];
        $i++;
    } 
}
vertexL_to_vertexR();
docker公式Alpine Linuxイメージを使ってmini_httpdでCGIを動かす

#環境
Dockerホスト - Alpine Linux 3.13.5
＃ESXi上に組みましたが、本質的にUbuntuでも何でも変わらないです。ちなみにメモリ384MB、HDD8GBです
Dckerバージョン - 20.10.6
Dockerイメージ - alpine:3.13.5
mini_httpd - 1.30-r1

#操作
##Dockerホストでの操作
###Dockerのインストール

dockerイメージのあるリポジトリを有効にします。

```:/etc/apk
host:~#vi repositories
#/media/cdrom/apks
http://dl-cdn.alpinelinux.org/alpine/v3.13/main
#http://dl-cdn.alpinelinux.org/alpine/v3.13/community
#http://dl-cdn.alpinelinux.org/alpine/edge/main
http://dl-cdn.alpinelinux.org/alpine/edge/community  <== '#'を削る
http://dl-cdn.alpinelinux.org/alpine/edge/testing    <== '#'を削る
```

で、いつものおまじない。

```
host:~# apk update
host:~# apk upgrade
```

そしてDockerをインストールします。

```
host:~# apk add docker
host:~# rc-update add docker boot
host:~# service docker start
```

再起動したら動作確認します。

```
host:~# docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
```

と出ればok。「dockerサービスが動いてないよ」というエラーが出たらrebootしてみてください。
で、サクッとalpineなコンテナを作って中に入ります。

```
host:~# docker container run -dit --name miniweb --hostname miniweb alpine:3.13.5 tail -f /dev/null
host:~# docker container exec -it miniweb /bin/ash
```
"miniweb"部分は適当に変えてください。

##Dockerイメージでの操作
いつものおまじない。

```
miniweb:~# apk update
miniweb:~# apk upgrade
```

そしてopenRCとmini_httpdをインストールします。

```
miniweb:~# apk add openrc
miniweb:~# mkdir /run/openrc
miniweb:~# touch /run/openrc/softlevel
miniweb:~# apk add mini_httpd
```

mini_httpdの設定ファイルを修正します。最低限必要なのはこれだけ。

```:/etc/mini_httpd
miniweb:~# vi mini_httpd.conf
port=80
user=minihttpd
data=/var/www/localhost/htdocs
cgipat=**.sh|**.cgi
nochroot
logfile=/var/log/mini_httpd/mini_httpd.log
```

適当にwebコンテンツを作ります。

```:/var/www/localhost/htdocs
miniweb:~#vi index.cgi
#!/bin/sh
echo "Content-type: text/html"
echo ""
set

miniweb:~# chmod +x index.cgi
```

mini_httpdを起動サービスに登録します。

```
miniweb:~# rc-update add mini_httpd boot
miniweb:~# rc-service mini_httpd start
miniweb:~# reboot
```

以上。
どっかからcurlででも試してみてください。

```
host:~# apk add curl
host:~# curl 172.17.0.2
...
(環境変数の一覧が出てきます)
...
```

#補足

最後の curl で「httpdがあがってない」エラーが出るときは mini_httpd サービスが起動していません。
手動で起動してみてください。

```
host:~# docker exec -it miniweb /bin/ash
miniweb:~# rc boot
miniweb~#:rc-satus
Runlevel: boot
 mini_httpd
...
```

'rc-service'や'rc-update'だと「もう起動してるよ」とエラーになります。
Apollo ServerのmockingでMockListが動かない

##Apollo ServerのmockingでMockListが動かない

開発段階などでmockingが便利。でもデフォルトだと2件しか取れなくて困る。

### 公式だとMockListの使用が書いてある
https://www.apollographql.com/docs/apollo-server/testing/mocking/#using-mocklist-in-resolvers

```
  Person: () => ({
    // a list of length between 2 and 6 (inclusive)
    friends: () => new MockList([2,6]),
    // a list of three lists each with two items: [[1, 1], [2, 2], [3, 3]]
    listOfLists: () => new MockList(3, () => new MockList(2)),
  }),
```

```
 "message": "Expected Iterable, but did not find one for field (field名)"
```

と言うエラーが出て利用できない。

## 空配列を入れるといいみたい
詳しく調べると、依存しているgraphQltoolsで更新があったみたい

https://www.graphql-tools.com/docs/mocking/#deprecated-mocklist

> Deprecated: MockList
> MockList is deprecated, use plain arrays instead. See Using lists in mocks.

```
{
  Person: () => ({
    // a list of length between 2 and 6
    friends: [...new Array(casual.integer(2, 6))],
    // a list of three lists of two items: [[1, 1], [2, 2], [3, 3]]
    listOfLists: () => [...new Array(3)].map((i) => [...new Array(2)]),
  }),
}
```

単純に空の配列を渡せばよしなにしてくれるようです。
casual.integer(2,6)で2から6までの数字がランダムで決まるので、配列の数も可変にできるので、同じ仕様になりました。
Next.js+framer-motionで画面遷移アニメーション

Next.js でReactのアニメーションライブラリであるframer-motionを使ったので、メモがてら記事にしたいと思います。

当方初投稿なので至らない点もあるかと思いますが、温かい目で見てもらえればと思います。

# はじめに

[Framer Motion](https://www.framer.com/api/motion/)とはReactで使用できるアニメーションライブラリです。純粋にアニメーションを実装しようとするとかなり複雑なものになってしまいますが、専用のコンポーネントを使うことで手軽にプログラムに組み込めるようになっています。

react-router-dom と組み合わせたものが多いですが、Next.js との相性も良さそうです。

# 前提

- Next.js v10.1.3
- TypeScript
- framer-motion v4.1.16

## framer-motionのインストール

npm でインストールできます。

```
npm install framer-motion
```

# コード

## _App.tsx

```typescript
import React from "react";
import type { AppProps } from "next/app";
import { AnimatePresence } from "framer-motion";

function MyApp({ Component, pageProps, router }: AppProps) {
  return (
    <div>
      <AnimatePresence exitBeforeEnter>
        <Component {...pageProps} key={router.route} />
      </AnimatePresence>
    </div>
  );
}

export default MyApp;
```

Next.js はファイル名を元にルーティングされるのでルーターの細かい設定は要りません。（楽！）

`<Component>` の中身がルーティングによって変わるので、その上を`<AnimatePresence>`で囲います。これはコンポーネントがアンマウントされた時のアニメーションを有効にするものです。

`exitBeforeEnter`のPropはコンポーネントがアンマウントされるのを待ってから次のコンポーネントに移るものです。これがないと遷移元のアンマウントと遷移先のマウントのアニメーションが同時に発火してしまいます。

子要素である`<Component>`には必ず`key`を追加してください。値はrouter.routeが一意な値を返してくれます。

## (任意のページ).tsx

```typescript
import React from "react";
import { motion } from "framer-motion";

export default function Home() {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      transition={{ ease: "easeOut", duration: 1 }}
    >
      <...>
    </motion.div>
```

各ページのコードでは`<motion>`コンポーネントでアニメーションを実装します。アニメーションの動きは以下のようになります。

- マウント時: initial → animate
- アンマウント時: animate → exit

transitionではアニメーションの種類(ease)や時間(duration)などを記述します。

framer-motionの機能についてはまだ把握しきれていない部分が多いので、省略します。かなり多彩なアニメーションを作ることができるみたいなので、是非[こちら](https://www.framer.com/api/motion/)を参照してみてください。

# まとめ

Next.js(React)でアニメーションを実装する時にはとても有用だなと感じました。是非導入を検討してみてはいかがでしょうか。

拙いながらも、アウトプットが大事だと思い記事を書いてみました。まだまだ足りないところばかりですが、今後も記事を投稿してみようと思うのでよろしくお願いいたします！

# 参考
- [Framer Motion](https://www.framer.com/api/motion)
- [【遊んでみた】framer-motion基本のき](https://dev.classmethod.jp/articles/play-framer-motion-basic/)
[Flutter] デバイスID取得の方法

Androidアプリ開発で個体識別IDを取得したい場面が出てきたので、実装したのを共有します。

## パッケージの取得

```yaml:pubspec.yaml
dependencies:
  flutter:
    sdk: flutter
  device_info: ^0.4.0+2
```
##出力
device_infoパッケージを`import`する

```dart:.dart
import 'package:device_info/device_info.dart';
```
```dart:.dart
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
print(androidInfo.androidId);  // デバイスID
```

##番外編
ID以外にもいろいろなデバイス情報を取得できるようです。

引用元(https://miajimyu.com/docs/flutter/flutter-use-device-info/)

```dart:.dart
  // Comments are example.
  Map<String, dynamic> _readAndroidBuildData(AndroidDeviceInfo build) {
    return <String, dynamic>{
      'version.securityPatch': build.version.securityPatch, // 2020-09-05
      'version.sdkInt': build.version.sdkInt, // 30
      'version.release': build.version.release, // 11
      'version.previewSdkInt': build.version.previewSdkInt, // 0
      'version.incremental': build.version.incremental, // 6903271
      'version.codename': build.version.codename, // REL
      'version.baseOS': build.version.baseOS, // 
      'board': build.board, // goldfish_x86
      'bootloader': build.bootloader, //unknown
      'brand': build.brand, // google
      'device': build.device, // generic_x86_arm
      'display': build.display, // sdk_gphone_x86_arm-userdebug 11 RSR1.201013.001 6903271 dev-keys
      'fingerprint': build.fingerprint, // google/sdk_gphone_x86_arm/generic_x86_arm:11/RSR1.201013.001/6903271:userdebug/dev-keys
      'hardware': build.hardware, // ranchu
      'host': build.host, // abfarm-us-west1-c-0007
      'id': build.id, // RSR1.201013.001
      'manufacturer': build.manufacturer, // Google
      'model': build.model, // sdk_gphone_x86_arm
      'product': build.product, // sdk_gphone_x86_arm
      'supported32BitAbis': build.supported32BitAbis, // [x86, armeabi-v7a, armeabi]
      'supported64BitAbis': build.supported64BitAbis, // []
      'supportedAbis': build.supportedAbis, // [x86, armeabi-v7a, armeabi]
      'tags': build.tags, // dev-keys
      'type': build.type, // userdebug
      'isPhysicalDevice': build.isPhysicalDevice, // false
      'androidId': build.androidId,
      'systemFeatures': build.systemFeatures,
    };
  }
```
###参考
[device_infoをつかってみる[Flutter]](https://miajimyu.com/docs/flutter/flutter-use-device-info/)
[[Flutter]デバイス情報の取得の仕方(iOS、Android)](https://nobushiueshi.com/flutter%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9%E6%83%85%E5%A0%B1%E3%81%AE%E5%8F%96%E5%BE%97%E3%81%AE%E4%BB%95%E6%96%B9ios%E3%80%81android/)

###会社の紹介
私は現在、[株式会社ダイアログ](https://www.dialog-inc.com/)という物流×ITの会社に勤務しております。
様々な職種を募集しているので、[Wantedly](https://www.wantedly.com/companies/company_3244501)のページをご覧ください。
大学に入って読んでよかった情報系の本４選！！！

# はじめに
　インターネットには日々様々な情報が投稿され、紙媒体の本の市場は日々縮小する一方。プログラミング関係の情報なんてまさにネットで無料に拾える情報の代表ですがそんな中で生き残っている本はすごくわかりやすく書かれていてお金を払う価値は十分あります。今回は私を難しい大学の課題から助けてくれ、さらにプログラミングの楽しさを教えてくれた本たちを紹介します。

# 【その１】斎藤康毅(2016)『ゼロから作るDeep Learning』オライリー・ジャパン
<a href="https://www.oreilly.co.jp/books/9784873117584/">出版社HP</a>
　理論は微分の考え方から、実装はPythonの環境構築から。まさにゼロからDeep Learningを教えてくれる教科書です。実際に手を動かしてみて手書き数字データセット「MNIST」で95%以上の精度が出た時は感動しました。さらに、CIFAR-10などのカラー画像や畳み込みの処理も記してあって本格的です。到達度は高いと思うのですが、少しずつ実装していくので詰まったら簡単に戻れるので挫折の心配はないでしょう。見やすいレイアウトも最高です。
　2巻ではリカレントニューラルネットワークの解説もあるのでさらにお世話になりそうです。Pythonのコードがなかなか理解できない方にはAtCoderで少し練習してから読むのもおすすめです。

# 【その2】掌田津耶乃(2020)『Python Django3 超入門』秀和システム
<a href="https://www.shuwasystem.co.jp/book/9784798061924.html">出版社HP</a>
　情報業界といえばAIとTwitter, Facebookなどのアプリケーションなどがまず思い浮かぶのではないでしょうか。私はそうでした。この本はDeep Learningの勉強でPythonを身につけた後に自分で物を作りたいという思いから購入したものでした。実際にその思いは尽きることなく、簡単なものですがDjangoで掲示板を作成し、サーバーを借りてドメインを取得し実際に公開することができました。<a href="http://colorful-wall.com/board/boards/">【ここに公開してます】</a>

# 【その3】Mana(2019)『1冊で全て身につくHTML&CSSとWebデザイン入門講座』SB Creative
<a href="https://www.sbcr.jp/product/4797398892/">出版社HP</a>
　自分でWebアプリケーションをつくるためのHTML,Webデザインの参考になりました。情報系の本には珍しく、とてもカラフルなデザインで読みやすいです。こちらも挫折の心配はいりません。

# 【その4】ミカエル・シプサ(2008)『計算理論の基礎』(太田和夫ほか訳)共立出版
<a href="https://www.kyoritsu-pub.co.jp/bookdetail/9784320122079">出版社HP</a>
　NP完全問題は競技プログラミングなどでよく出くわしますが、それがどのような理論に基づいているのか知っている方は少ないのでは?
　この本では全てのNP問題がSATに多項式帰着することを示すクック-レビンの定理をはじめ、さまざまな重要問題が登場して非常に興味深いです。前提知識は意外と多くないので、計算理論が専門でなくても読めるようになっています。

# 最後に
そのほかに面白かった本があれば追加していく予定です。JavaScriptの練習本とかも面白いのでいつか紹介したいです！
CMake 3.20からIntel oneAPIがサポートされた件

# 要約

- CMake 3.20.0以降で、Intel oneAPIのC/C++/Fortranコンパイラがサポートされる（一部OS除く）。
  - Intel oneAPI 2021.1以降の新世代C/C++コンパイラ(`icx`/`icpx`)は、Windows/Linux両方でサポートされている。
  - Intel oneAPI 2021.1以降の新世代Fortranコンパイラ(`ifx`)は、現時点でLinuxのみサポートされている。
- コンパイラID
  - `icx`/`icpx`/`ifx`：`IntelLLVM`
  - `icc`/`icpc`/`ifort`：`Intel`（変更なし）
- CMake 3.20.2でIntel oneAPIに係るバグ修正があったので、CMake 3.20.2以降、およびIntel oneAPI 2021.2以降を使うこと（両方共2021年5月13日現在の最新版）。

# 参考

[CMake 3.20 Release Notes](https://cmake.org/cmake/help/latest/release/3.20.html#id3)
satasmodelsのソースコードを追ってロジスティック回帰の回帰係数の標準誤差の計算を確認した話

<b>結論は対数尤度関数のへシアン（Fisherの情報量行列）の逆行列の対角成分</b>なんだけどソースコード追っかけるのに割と時間を食ったのでメモを残す。

## 設定
- statsmodels ver0.12.2
- statsmodels.discrete.discrete_model.Logitを利用したロジスティック回帰分析について調べました

## 要旨
```statsmodels.discrete.discrete_model.Logit ```の戻り値のsummaryメソッドを実行した時に表示される回帰係数の標準誤差は```Logit.hess()```で計算される対数尤度関数のへシアンの逆行列の対角成分。

## 本題
Logitのfitを実行すると返されるのはstatsmodels.discrete.discrete_model.BinaryResultsWrapper
これのsummaryメソッドを実行した時に表示される回帰係数の標準誤差がどう計算されているか知りたかった

BinaryReuslts.summary()内でさらに
Super(DiscreteResults)のsummaryメソッドを呼び出している
そこでさらにstatsmodels.iolib.summaryのadd_table_paramsメソッドを呼び出して、さらに同じクラス内のsummary_paramsメソッドにとぶ。
そこでようやくstd_errにresults.bseを代入しているのを発見。

もう一度BinaryResultsクラスに戻るがこの中でも、親クラス（DescreteResults）でも標準誤差を計算している様子はない。のでさらに親クラス（LikelihoodModelResults)まで戻ってようやくbse()というメソッドを発見・・・・長かった。
bse()の中身は同じクラス内のメソッドcov_params（）を呼び出していて、、、、まだ旅が続く
cov_params()、if分岐が多くてミスってる可能性あるけど、基本設定（特にへシアンとかの計算に自作の関数与えてない）では多分self.normalized_cov_params * scaleを返しているだけ。
normalized_cov_paramsは```__init__```内で引数で与えられているので、、、ようやくコード内で、```BinaryResults(DescreteResults(LikelihoodModelResults))```にnormalized_cov_paramsを渡している箇所を見ればいいことにたどり着く。

元々BinaryResulutsはLogit.fit()の戻り値だったので、今度はLogit.fit()を辿るたびに出るが、、こっちはもはや長旅の後の下り坂みたいなもんで、大したことはない。
LogitのfitはSuper(BinaryModel)のfitを呼び出しているので、そっちをみにいくと、そこで定義されていないから、さらにその上のDiscreteModelを見に行く、、、、ここでもfitは親（base.LikelihoodModel)のfitを呼び出していて、、、LikelihoodModel.fit()の中で、```LikelihoodModelResults(self,xopt,Hinv```とnormalized_cov_paramsにHinvを渡している箇所を発見！！！

Hinvは同fitメソッドの中で計算されている```H = self.hessian(xopt) ```の逆行列で、hessian()はLogitの中で定義されているからこれで行き着いた！！

<b>BinaryResults.summary()で表示されるロジスティック回帰の回帰係数の標準誤差は対数尤度関数のへシアンの逆行列の対角成分！！！</b>


## TODO
へシアンの逆行列を標準誤差に使っているのはパラメタの推定量の分散の下限はクラメル・ラオの定理でFisherの情報量行列の逆行列が下限だと知られているから。最尤推定量の時その分散は下限に一致することを使っている。
そのうちこれについてもまとめたい。
sprintfで書式を整える

$date = sprintf('%04d年 %02d月 %02d日', 2021, 5, 13);
print($date);

//%の後の数字（04etc）で表記する桁数を指示している
//dは数字の意味で、数字以外が記入されたときにエラーで弾くようになっている。
//※これだけで万全ではないので、注意

//文字を書きたいときは、d→sに変更するとＯＫ
React Nativeで文字幅を取得する

Webなら文字幅は `1ch` で取得できるが、React Nativeでは `px` `%` での指定しかできないので、要素の幅を取得することで擬似的に取得することにした。

## ポイント
* Textの `onLayout` を使って要素の幅を取得する。
* padding, margin, borderなどの余白は0にする
* 1文字の幅を取得したい場合、文字数で割る

## 注意点
* 等幅フォントでなければ、文字数で割っても正確な幅にはならない

* 画面の解像度に合わない（切りの悪い）px幅の場合、最も近いピクセルに合わせられてしまうため、表示と合わない

例）

| 計算値 | 画面上の表示幅 |
|--:|--:|
| 10.75px | 10.5px |
| 9.8px | 10px |

```tsx
import React, {Component} from 'react';
import { Text, View, StyleSheet } from 'react-native';

type Props = {}
type State = {
  charWidth: number
}

const text = 'A'

export default class App extends Component<Props, State> {
  constructor(props: Props) {
    super(props)
    this.state = {
      charWidth: 0,
    }
  }

  render() {
    return (
      <View style={styles.container}>
        <View style={styles.textBox}>
          <Text
            onLayout={(e) => {
              this.setState({
                charWidth: e.nativeEvent.layout.width,
              })
            }}
            style={styles.char}
          >
            {text}
          </Text>
        </View>
        <Text>Size: {this.state.charWidth}px</Text>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  textBox: {
    display: 'flex',
    flexDirection: 'row',
  },
  char: {
    fontSize: 18,
    fontWeight: 'bold',
    textAlign: 'center',
    backgroundColor: '#eee',
    padding: 0,
    margin: 0,
    borderWidth: 0,
  },
});

```
Demo: https://snack.expo.io/TRAFtndhu
UiPathでエクセルのマクロを実行＆メッセージのOKを押す

例えば、「実行するとメッセージボックスが出現するマクロ」をUiPath上で実行する場合…
![macro1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/df2b4ac5-199d-a4f5-f401-f3e6568127c3.jpeg)
「Execute macro」アクティビティに、実行したいマクロ名を記入すればOKです。
※「Execute macro」は、ExcelApplicationScope内でのみ使えるアクティビティです。
![macro2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/e22ceaf1-f6e9-d112-b889-a435fc9e9fa9.jpeg)

ただし、”マクロが出現させるメッセージボックスのOKボタン”を押したい場合、
「上からmacro→Click」という設定では、UiPahtはOKボタンを押してくれません！
![macro5.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/dc16a5fd-fe96-ed8f-eba6-a8cfa0bc0945.jpeg)

「Parallelの中に、左からmacro→Click」という設定にすれば、OKボタンは押されます。
![macro4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/9fdb6bba-4164-c1d0-4022-4ef4e7117107.jpeg)
Angular Universalに対応したIonicアプリをGAE環境で動かす

[前回の記事](https://qiita.com/nakano-shingo/items/7d82567cd330fb855e99)で、Ionic5のAngularアプリをGAE環境で動かすメモを残したが、そのアプリでSSRに対応するために`@ionic/angular-server`を導入してGAEで動かした

## 手順

### 1. 必要なpackageを追加

```bash
ng add @nguniversal/express-engine

npm install --save @ionic/angular-server

npm install --save @angular/animations
# Required by @angular/platform-server (from @ionic/angular-server)
```

### 2. CloudBuildで利用するDockerfileを変更

```Dockerfile
FROM node:12-alpine as buildContainer
WORKDIR /app
COPY ./package.json ./package-lock.json /app/
RUN npm install
COPY . /app
RUN npm run build:ssr

FROM node:12-alpine
WORKDIR /app
COPY --from=buildContainer /app/package.json /app
COPY --from=buildContainer /app/dist /app/dist
COPY --from=buildContainer /app/dist/app/server /app/dist/app/server
EXPOSE 4000
CMD ["npm", "run", "serve:ssr"]
```

Dockerイメージからnginxにnodeに変更して、node側でWebサーバを立てるようにしている
※ npm buildの結果をDockerコンテナ内にコピーするパスは、`/www`から`/app/dist`に変更した

### 3. Build & Deploy

```bash
npm run build:ssr  # 「ionic build --prod」または「ng run app:build:production」から変更
gcloud builds submit
gcloud app deploy --image-url us.gcr.io/your-app-name/angular-nginx-container
```

### 4. 動作確認

[ここらへん](https://www.javadrive.jp/javascript/start/index1.html)を参考に、ブラウザのJavaScriptを無効にしてからページを読み込み

![GAEの画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/165108/5d439bb2-6480-e571-3339-4de8e663f045.png)


ioniconsが表示されてないが、ちゃんとSSRされている。良さそう！

---

※ 前回の記事で作成した、以下のファイルは必要なくなったので削除した

- nginx.conf
- .dockerignore
- src/assets/envconfig.js 
- src/assets/envconfig.template.js

## 参考

- [SSR with Angular Universal And Ionic - Ionic Blog](https://ionicframework.com/blog/ssr-with-angular-universal-and-ionic/)
- [Server Side Rendering (SSR) - Ionic 5 Full Starter App](https://ionic-5-full-starter-app-docs.ionicthemes.com/server-side-rendering-ssr)
- [node.js - Deploying Angular Universal 9 to Google App Engine - Stack Overflow](https://stackoverflow.com/questions/65339947/deploying-angular-universal-9-to-google-app-engine)
I
【Python × Excel】OpenpyxlでVlookupをやってみる

#はじめに
PythonでExcelを操作していて、Vlookupしたいときありませんか？Vlookup便利ですよね。
ということでOpenpyxlを使ってブックをまたいでVlookupする方法を解説します。

今回は下記の評価データと給与データをサンプルとして使用します。

評価データ
![評価.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646654/ecb0e63a-a4c0-6147-3cb9-53445376918d.png)

給与データ
![給与.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646654/ec67c105-e969-3d88-de9c-02e3c1298d7b.png)

#準備
必要なライブラリをインストールしましょう。今回使うのはOpenpyxlです。

```python
import openpyxl as px
```

#必要ファイルの読み込み
ここで評価データと給与データの２つのエクセルを読み込みます。

```python
wb = px.load_workbook("C:\\Users\\ユーザー名\\Documents\\Qiita用サンプル\\評価データ.xlsx")
ws = wb["評価"]
wb2 = px.load_workbook("C:\\Users\\ユーザー名\\Documents\\Qiita用サンプル\\給与データ.xlsx")
ws2 = wb2["給与"]
```

#Vlookup
いよいよVlookupをしていきます。

```python
#Get last row
lastrow = ws.max_row
lastrow2 = ws2.max_row

#get values from IMaster Sheet
for i in range(2, lastrow + 1):
    name_hyoka = ws['B' + str(i)].value
    for j in range(2, lastrow2 + 1):
        name_salary = ws2['A' + str(j)].value
        # get values by vlook up
        if name_hyoka == name_salary:
            salary = ws2['B' + str(j)].value
            ws.cell(row = i, column = 5, value = salary)
            break

#Save
def save():
    wb.save(filename = "C:\\Users\\ユーザー名\\Documents\\Qiita用サンプル\\評価データ_給与.xlsx")
save()
```
上記コードでは、評価データの社員名を検索値として給与データの社員名カラムで検索をかけています。そして社員名が一致した場合は給与データの給与を、評価データのE列に書き込むようにしています。

ポイントは
①２つのシート入れ子にする形でそれぞれをForループで回す。
②if文で文字列一致の判定をする。
③一致していた場合のみ値をセルに書き込む
④break忘れない＊ここ大事
⑤最後にwbを保存

データの読み込みはカラムのアルファベット指定で出来たのですが、書き込みの時はそれがうまくいかなかったので数字でカラムを指定しています。

ちなみにbreakを入れるのは文字列一致を発見した後、再び外側のループに戻って次の検索値を検索するためです。


コード全体としてはこんな感じです。

```python
import openpyxl as px

wb = px.load_workbook("C:\\Users\\ユーザー名\\Documents\\Qiita用サンプル\\評価データ.xlsx")
ws = wb["評価"]
wb2 = px.load_workbook("C:\\Users\\ユーザー名\\Documents\\Qiita用サンプル\\給与データ.xlsx")
ws2 = wb2["給与"]

#Get last row
lastrow = ws.max_row
lastrow2 = ws2.max_row

#get values from IMaster Sheet
for i in range(2, lastrow + 1):
    name_hyoka = ws['B' + str(i)].value
    for j in range(2, lastrow2 + 1):
        name_salary = ws2['A' + str(j)].value
        # get values by vlook up
        if name_hyoka == name_salary:
            salary = ws2['B' + str(j)].value
            ws.cell(row = i, column = 5, value = salary)
            break

#Save
def save():
    wb.save(filename = "C:\\Users\\ユーザー名\\Documents\\Qiita用サンプル\\評価データ_給与.xlsx")
save()
```

動作の結果はこちらです。
![vlookup後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/646654/c88097f4-b76b-5667-9ac5-4bbe989d7bd8.png)

E列に給与が入ってますね。


#参考にしたサイト
https://fastclassinfo.com/entry/python_excel_vlookup/
こちらのサイトの解説を参考に実践しました。
ConoHaのVPSでUbuntuのデスクトップを使ってChromeの自動化

conohaのVPSで、Ubintu２０.04のディスクイメージで、サーバーを作りました。
その後、コンソールのボタンをクリックして、コンソールを起動します。
![スクリーンショット 2021-05-13 6.43.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/03a9adfc-c28e-07b5-3449-cbee1add8698.png)

コンソールで、こちらのコマンドを実行します。

```bash
$ apt -y install ubuntu-desktop
```
インストールが終わったら、再起動します。

```
$ reboot
```
こちらの記事を参考にしました。


[Ubuntu20：デスクトップ環境設定](https://centos.rcg.jp/ubuntu20_desktop/)


日本語入力ができなかったので、こちらの記事を参考にしました。
[Ubuntu20.04で日本語入力(Mozc)を可能にする方法](https://novicengineering.com/ubuntu_mozc_install/)

Chromeをインストールしたかったのですが、ソフトウェアインストールが見つからなかったので、こちらの記事を参考にしました。

[Ubuntuにダウンロードしたソフト(.deb）をインストールする方法](https://freepc.jp/post-31340)

##Chromeで自動化
実は、Chromeの拡張機能の「iMacros for Chrome」を使いたかったのです。
今までは、WindowsのリモートディスクトップでChromeを使っていました。

でも、コスト節約を考えてUbuntuでChromeを起動して、自動化を試みたかったのです。

今回自動化ができたことを確認できたので、良かったです。

![スクリーンショット 2021-05-13 20.03.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/38dad0d8-f8ce-92a3-4391-adab92502349.png)

##Xrdpサーバーのインストール
```
sudo apt -y install xrdp tigervnc-standalone-server
```

##Xrdpサーバーの起動

```
$ /lib/systemd/systemd-sysv-install enable xrdp
```

こちらの記事を参考にしました。

[Ubuntu20：デスクトップ環境設定](https://centos.rcg.jp/ubuntu20_desktop/)

##ログイン画面について

Xrdpのクライアントのソフトを使って、ログインできます。
ログインの情報は、通常のデスクトップにログインするユーザー名とパスワードです。

ログインを試みるとエラーになり、このログイン画面が表示されます。
![スクリーンショット 2021-05-14 20.58.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/f33ef42d-bdc7-c682-6f51-7c0035b73306.png)

そのため、SessionをXVNCに切り替えて、もう一度ログインを試みると、ログインできます。

![スクリーンショット 2021-05-14 20.58.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/2caadbc4-8af0-240c-46bd-741b3b628447.png)

##ログイン成功画面
![スクリーンショット 2021-05-14 20.50.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/241493e7-1425-a881-d57d-a57a0e6593f2.png)


##スマホからログインした画面
![IMG_20210515_001415.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/100c47be-4a00-077c-5178-87b779d78e02.jpeg)
phpMyAdminのインポートファイルサイズ上限緩和

仮想環境でちょっとしたデータベース作業を行う際に、久しぶりにphpMyAdminを使いました。
久しぶり過ぎて、何か所か行き詰ってしまったところがあったので、既出のものばかりかもしれないけど、備忘録として投稿。
# 行き詰まったところ
60,000行を超えるレコード数を持った約20MBほどのCSVファイルをインポートさせると、読み込みの途中でエラーになってしまう。
SELECT DISTINCTで重複レコードをまとめるSQLを発行したにも関わらず、ダブって表示されてしまう。（大文字小文字を区別していない）

# 検証環境
まずは、サーバーのスペックなど。仮想ホストにはVMware ESXiを利用しています。

| 項目 | 内容 |確認用のコマンド|
|:-----------|:------------:|:-:|
| OS         | CentOS Linux release 7.9.2009 (Core)|cat /etc/redhat-release|
| Web Server | Apache/2.4.6 (CentOS)| httpd -v|
| PHP        | PHP 5.4.16 (cli) (built: Apr  1 2020 04:07:17)| php -v|
| DB server  | mariadb-server-5.5.68-1.el7.x86_64| rpm -qa &#124; grep -i mariadb|
| phpMyAdmin | phpMyAdmin-4.4.15.10-4.el7.noarch| rpm -qa &#124; grep -i phpmyadmin|

# 設定ファイルを修正する
さまざまなphpの設定をするphp.iniを修正。インポートファイルのサイズ制限もここで変更。
## デフォルト値

```/etc/php.ini
upload_max_filesize = 2M
post_max_size = 8M
```

今後のことも考えて、大幅にアップさせることにしました。
## 変更後

```/etc/php.ini
upload_max_filesize = 32M
post_max_size = 128M
```
Webサーバーを再起動させ反映させる。

```
# systemctl restart httpd
```
## 注意点
upload_max_filesizeだけ変更しても上限8,192KBになってしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/5ac76c70-8cce-399f-54ee-ac404e43017d.png)
post_max_sizeも変更する。
すると32MiBに変わる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/c7ca7594-3fdb-ede9-47e7-1b8c6ec48548.png)

# 大文字小文字の区別
調べたらところ、バイナリにすることで解決するようだ。
該当カラムの照合順序を「utf8_bin（UNICODEバイナリ）」に指定することで解決。
※デフォルトで作ると「utf8_general_ci（UNICODE・大文字小文字を区別しない）」で作られるみたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520646/7f80c91e-8a26-ef61-60c6-b46d71352181.png)
AWS初心者の俺がたった10日でAWSプラクティショナーに合格した件。

# はじめに
クラウドファーストのこの時代。トップシェアを誇るAWSの知識は全エンジニアにおいて不可欠なものになりました。
自分は、インフラ案件に携わったことが無いAWS初心者でしたが、まずは手始めに「AWSプラクティショナー」の資格を取ろうと思いました。
短期間で取得したかったので、計画的に学習した結果、約10日で取得出来ました。
`「どうやって短期間で取るのか？」`に重きを置いて解説したいと思います！

# AWSプラクティショナーとは？

> AWSクラウドの知識とスキルを身に付け、全体的な理解を効果的に説明できる個人が対象です。その他の AWS 認定で扱われる特定の技術的役割からは独立しています。(中略)
AWS認定クラウドプラクティショナーは、アソシエイト認定または専門知識認定を取得するために推奨される任意のステップです。

(参照) [AWS 認定 クラウドプラクティショナー]
(https://aws.amazon.com/jp/certification/certified-cloud-practitioner/)

AWSを利用する上での基本的な知識を中心とした問題が出題されるので、基礎を押さえるという意味では最適です。

ここでは、出題範囲や合格点数など詳しいことは解説しませんので、詳しくは以下を参照ください。

(参照) [クラウドプラクティショナーとは？難易度や合格率、おすすめ参考書について]
(https://www.acrovision.jp/service/aws/?p=706)


## 使用した教材
自分は、Udemyの以下の教材２つを利用して学習しました！
正直、この２つで事足りると思います。

①[これだけでOK! AWS認定クラウドプラクティショナー試験突破講座（豊富な試験問題290問付き）]
(https://www.udemy.com/course/ok-aws-e/)

②[この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問）]
(https://www.udemy.com/course/aws-4260/)

※Udemyは教材が高いのでセール中に購入することをおすすめします！(意外と頻繁に開催してます)


## 学習スケジュール
ここでは、自分が実際に行った学習の大まかなスケジュールを書いています。
全く同じにしなくても良いですが、参考になればと思います！

### 1〜3日目
3日目までに、「①」の教材を終了させます！
ここでは、大まかな全体像を掴むために動画を見て聞いて、「こういったものがあるんだ」程度に理解しておきましょう！
※全部で約10.5時間あるので、３時間/日で完了出来ます。

### 4日目
4日目は、動画内で使用されているPDFのスライドショーが「①」の教材に添付されているので、それを読みましょう！
動画で見るよりも、スピーディに進めるので2周ほど読みながら覚えるようにしましょう。

### 5日目
5日目は、「①」の教材の最後にある問題集を行います！
最初は、低い点数で心が折れそうになるかもしれませんが、自分も最初はとても低かったので安心してください！笑
2つの模擬問題集がついていますが、それぞれ終わった後は、`正解・不正解問わずに解説を読んで理解を深めて`ください。
これも2,3周ほどすれば８０点くらい取れてくると思うので、80点を目標に学習しましょう！

### 6〜8日
8日目までに、「②」の教材の問題集を全て80点以上取れるようにします。
これも、2,3周ほどすれば８０点くらい取れてくると思うので、「①」の教材の問題集と同じく、80点を目標に頑張りましょう！

### 9日目
おそらくここまでついてこれてる人は、かなり基礎が固まっていると思います。
9日目では、「①」と「②」の教材の問題集を全てやり直してみましょう！
ここでは、90点以上取れているのがベストかなと思います。
前回よりも良い点数になっていれば、及第点です！

### 10日目
自分の場合は試験当日。
朝早くに起きて、問題集を片っ端から解いていきます。(この時点でかなり知識が付いているので、問題集もすぐ終わると思います。)
解説まで読み終えたら、あとは残り時間PDFのスライドショーの資料をひたすら読むことです。
この`スライドショーの資料は大事な情報が詰まっている`ので、重宝してください！

## 合格するためのコツ

### アウトプットを忘れない
学習をしていると、自分の得意な部分や、なかなか覚えられない部分が出てきます。覚えられない部分に関してはアウトプットをすることで知識を定着させましょう！
自分の場合は、Twitterに簡潔にツイートすることで理解度を深めることが出来ました。
アウトプット方法は、各自自由で大丈夫です！

### 問題集の解説を読む
解説には、教材の動画中には説明してくれていなかったことまで書いてあります。
実際に、`動画以外の範囲で試験でも問題が出ましたが、解説を読んでいたので対応できました！`

### 無理せず自分のペースで
「自分は短期間で取ってやる！」という強い意志があったので、大丈夫でしたが、ここまで速攻で取得しなくてもいい人はペースを緩めて、ゆっくりでも大丈夫です。
その際は、問題集を100点取るつもりで頑張りましょう！
※ちなみに自分は、全ての問題集を試験前には100点取れるようにしていました笑

# おわりに
どうでしたでしょうか？？
プラクティショナー試験は学習すれば、大体の人は合格出来ると思うので、実績のある僕の学習方法でぜひ合格を目指してみてください！！！
【Ansible】skipした内容がregisterに格納される場合の回避策

### はじめに
　以下のplaybookのように、変数（sample_bool）にもとづいてregisterの内容を変更したいことが
あると思いますが、registerはskipされたことが変数に格納されてしまうので、
「when: sample_bool is false」にしていても、__regiter変数（register_result）が上書き
されてしまいます__。

```yaml:register_test_1.yml
---
- hosts: localhost
  gather_facts: false
  vars:
    sample_bool: true
  tasks:
    - name: "debug true"
      debug:
        msg: "debug true"
      register: register_result
      when: sample_bool is true

    - name: "debug false"
      debug:
        msg: "debug false"
      register: register_result
      when: sample_bool is false

    - name: "debug register_result"
      debug:
        var: register_result
```

```text:出力
(venv) [centos@ip-<ip addr> ansible]$ ansible-playbook register_test_1.yml 

PLAY [localhost] *******************************************************************************************************

TASK [debug true] ******************************************************************************************************
ok: [localhost] => 
  msg: debug true

TASK [debug false] *****************************************************************************************************
skipping: [localhost]   # skipされているが、regiter変数（register_result）は上書きされる

TASK [debug register_result] *******************************************************************************************
ok: [localhost] => 
  register_result:    # regiter変数に「debug true」が格納されていない
    changed: false
    skip_reason: Conditional result was False
    skipped: true

PLAY RECAP *************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
```

### 1. playbook紹介
　以下のように、registerの内容をset_factで変数（fact_result）に退避するようにすれば
register変数（register_result）が上書きされても問題ありません。

```yaml:register_test_2.yml
---
- hosts: localhost
  gather_facts: false
  vars:
    sample_bool: true
  tasks:
    - block:
        - name: "debug true"
          debug:
            msg: "debug true"
          register: register_result

        - name: "set fact"
          set_fact:
            fact_result: "{{ register_result }}"
      when: sample_bool is true

    - block:
        - name: "debug false"
          debug:
            msg: "debug false"
          register: register_result

        - name: "set fact"
          set_fact:
            fact_result: "{{ register_result }}"
      when: sample_bool is false

    - name: "debug result"
      debug:
        var: fact_result
```
【Laravel】Seederファイルを作成して、ダミーデータを格納する

Seederファイルの作成が初見だったためメモです
 
## ファイルの作成

```
$ php artisan make:seeder 任意のファイル名
```

作成したファイルに以下のように記述しました。色んなパターンあると思います

```php
<?php

use App\Models\Company;

class CreateCompanySeeder extends Seeder
{
    public function run()
    {
        $menu = Company::create([
            'name' => 'hoge-company'
        ]);
     }
}
```

## 作成したファイルを実行するように記述する　

```php:/database/seeds/DatabaseSeeder

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(CreateCompanySeeder::class);
    }
}
```

## 実行

```
$ php artisan db:seed
```

クラスを指定しても実行できる

```
$ php artisan db:seed --class=CreateCompanySeeder
```
macOS hdiutilコマンドの詳細調査

# hdiutil
指定されたサイズまたは指定されたデータから新しいイメージを作成する。
イメージが既にある場合は、-ov を指定しなければcreateは失敗する。

## オプション
-srcfolder source
sourceに指定した内容をファイルごとimageにコピーし、ファイルシステムを作成

-fs filesystem
---
##### 選択可能なフォーマット
- UDF (Universal Disk Format)
- MS-DOS FAT12
- MS-DOS MS-DOS
- MS-DOS FAT16
- MS-DOS FAT32
- HFS+ (Mac OS Extended)
- Journaled HFS+ (Mac OS Extended(Journaled))
- ExFAT
- APFS (macOS 10.3以降)

Case-sensitive(大文字小文字区別)
- Case-sensitive HFS+ (Mac OS Extended (Case-sensitive))
- Case-sensitive Journaled HFS+ (Mac OS Extended (Case-sensitive, Journaled))
- Case-sensitive APFS

APFSのメリット
1. 64bitになったので、より多くのファイルを扱える
2. 新規作成してから既存を削除する上書きになったので、従来のような途中で落ちてしまいファイル破損するリスクがなくなった

APFSのデメリット
1. macOS 10.12以降にしか使えない

-format FORMAT
---
このオプションを指定しない場合は、UDZO(Apple UDIF読み出し専用圧縮(zlib) Media)が自動適用される。
※UDIF => Universal Disk Image Format

UDRW: Apple 読み出し/書き込み Media
UDRO: Apple UDIF読み出し専用 Media
UDCO: Apple UDIF読み出し専用圧縮(ADC) Media
UDZO: Apple UDIF読み出し専用圧縮(zlib) Media
ULFO: Apple UDIF読み出し専用圧縮(lzfse) Media (macOS 10.11以降)
ULMO: Apple UDIF読み出し専用圧縮(lzma) Media (macOS 10.15以降)
UDBZ: Apple UDIF読み出し専用圧縮(bzip2) Media (macOS 10.4以降)
UDTO: DVD/CD-R Media
UDSP: Apple スパース・ディスクイメージ Media
UDSB: Apple スパースバンドル・ディスクイメージ Media
UFBI: MD5 チェックサム付き Apple UDIF読み出し専用 Media

以下フォーマットアルゴリズム

ADC(Apple Data Compression): Appleが独自に開発した古い圧縮方式[1]
zlib: RFC 1950で仕様化されたデータの圧縮および伸張を行うためのフリーのライブラリ[2]
lzfse(Lempel–Ziv Finite State Entropy) : Apple Inc.が開発したオープンソースの可逆データ圧縮アルゴリズム[3]
lzma(Lempel-Ziv-Markov chain-Algorithm) : 7Zip等で使用されているアルゴリズム[4]
bzip2: Burrows-Wheelerアルゴリズムを採用した、フリーでオープンソースのファイル圧縮プログラム[5]

# 参考文献
[1][Apple Data Compression (ADC) Scheme](https://www.npmjs.com/package/apple-data-compression)
[2][Zlib](https://zlib.net)
[3][lzfse/lzfse](https://github.com/lzfse/lzfse)
[4][lzma](https://www.freebsd.org/cgi/man.cgi?query=lzma&sektion=1&manpath=FreeBSD+8.1-RELEASE)
[5][bzip2](https://www.sourceware.org/bzip2/)
Laravelレイアウト

##Laravelレイアウト
共通したデザインのページを使える様になる

`@yield(名前)` : `@section`の内容をはめ込んで表示させる機能がある

まずベースとなるテンプレートを作る
viewにlayoutフォルダを作成、その中にファイル作成


```ruby:view/layouts/helloapp.blade.php
{{-- ベースとなるレイアウト用のテンプレート --}}
<html>
    <head>
        {{-- @yield配置場所を示す場所なのでendセクションはない --}}
        <title>@yield('title')</title>
        <style>
            body {font-size:16px; color:pink; margin:5px;}
        </style>
    </head>
    <body>

        <h1>@yield('title')</h1>

        @section('menubar')
        <h2 class="menutitle">メニュー</h2>
        <ul>
            <li>@show</li>
        </ul>

        <hr size="1">

        {{-- この部分にコンテントが読み込まれる --}}
        <div class="content">
            @yield('content')
        </div>

        {{-- この部分にfooter読み込まれる --}}
        <div class="footer">
            @yield('footer')
        </div>
    </body>
</html>
```

####`@section`は2種類の書き方がある

```ruby:view/index
{{-- extendで継承する　ベースレイアウトにそって内容を入れていく --}}
@extends('layouts.helloapp')

<!-- sectionは2種類書き方がある -->
<!-- ① セクション名、　設定するテキスト値-->
@section('title', 'INDEX')

{{-- ②　endセクションで囲う --}}
@section('menubar')
    {{-- 親(継承)の表示を指示できる --}}
    @parent
    インデックスページ
@endsection

```

ブラウザで見ると下記の様な表示になる
'view/layouts/helloapp.blade.php'を継承した'view/index'のページ

```
<h1>INDEX</h1>
<h2>メニュー</h2>
  <ul>
    <li>インデックスページ</li>
  </ul>
```

<hr>


###`@components`
一部を切り離して作成、組み込みたい時に
下記が部品の様な役割

```ruby:view/components/message
<div class="message">
    <p class="msg_title">{{$msg_title}}</p>
    <p class="msg_content">{{$msg_content}}</p>
</div>

```

```ruby:view/index
 {{-- どのテンプレートか指定している'view/components/message' --}}
    @component('components.message')
        {{-- スロットは{{}}で指定された変数に値を設定できる --}}
        @slot('msg_title')
        これはメッセージ
        @endslot

        @slot('msg_content')
        これもメッセージ
        @endslot
    @endcomponent
```


```
<p>これはメッセージ</p>
<p>これもメッセージ</p>
```

<hr>

##`include`サブビュー

componentsと似ているが単純にテンプレートを表示させるのみの場合有効
`@slot`などはサブビューで利用できない

`@include(テンプレート名, [値の指定])`

```ruby:view/index
@include('components.message', ['msg_title'=>'OK', 'msg_content'=>'NOT OK'])
```

```
<p>OK</p>
<p>NOT OK</p>
```
【Vue.js】コンポーネントはパスカルケースで書くのがオススメ

## はじめに
仕事で使う事になったので1からVue.jsについて学んだ。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。

## コンポーネントはパスカルケースで書くのがオススメ
コンポーネント（single file component）の命名方法は以下の2つが選択肢にある。

| # | 具体例 |
|:-:|:-:|
| ケバブケース | hello-world |
| パスカルケース | HelloWorld |

が、命名時はパスカルケースを用いるのがオススメでその理由は以下。

1. 　パスカルケースはJavaScriptでよく使われるため、エディターで開発する際に自動補完されやすい
1. 　HTML要素と見分けがつきやすい（HTMLの要素・タグはケバブケースで書くため）<br>　以下の画像のように、`LikeNumber`は緑色だが、`like-header`は青色でHTMLの要素(divタグ)と同じで見分けにくい[^3]![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/3aeb63b4-7c10-10bf-773a-4ccecf87f904.png)
1. 　Vue.js以外のWebコンポーネントを使う際に見分けがつきやすい

[^3]: `LikeNumber`は[Global登録したコンポーネント](https://qiita.com/yuta-katayama-23/items/fa176f65162e6d4dd2cb)。<br>`like-header`は[Local登録したコンポーネント](https://qiita.com/yuta-katayama-23/items/fa176f65162e6d4dd2cb)で、`LikeHeader`をケバブケースで書いたもの。<br>※Vue.jsではコンポーネントをパスカルケースで定義しtemplateではケバブケースで記述するという事ができる。<br>※また、`LikeHeader": LikeHeader`の部分は`"like-header": LikeHeader`とも書ける。

### 余談
DOMテンプレート[^1]の場合は、**ケバブケース**で記載しなければならない。
理由は、

- ブラウザがDOMを描画する際には、htmlファイル→JavaScriptsファイルの順番で読み込む
- ブラウザがhtmlファイルを読み込む際には大文字小文字は区別されない

という2つの事があり、DOMテンプレートでパスカルケースを使うと全て小文字と認識され[^2]意図しない動きになるため。

[^1]: HTML上(.htmlファイル)に定義するコンポーネント
[^2]: `HelloWorld` → `helloworld`と見なされる

## Vue.jsの勉強メモ一覧記事へのリンク
Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。

- https://qiita.com/yuta-katayama-23/items/dabefb59d16a83f1a1d4
スプレッドシートが更新されたらMicrosoft Teamsに通知を送る。

#この記事について
スプレッドシートが更新されたらMicrosoft Teamsで通知が欲しかったのでIFTTTで実装した時の方法についてのメモです。とても簡単で無料で実装できました。

チームのインシデント管理なんかを共有スプレッドシートで行っていて、誰かが新しいインシデント（行）を追加したらチームメンバ全員が参加するチャネルに通知がほしい、そんなケースに使えるかなと思います。


#用意するもの
- Googleアカウント 
- Googleスプレッドシート
    - 監視対象となるシート。共有化されていること。上記で用意したGoogleアカウントに閲覧権限以上の権限が付与されていること。
- IFTTTアカウント
    - 今回はGoogleアカウント経由ログインを選択した。
- Teamsアカウント
    - webhookを追加するために管理者権限が必要な場合があります。
- Teams通知先チャネル

#手順概要
- 【Teams】通知先チャネルでWebhookを有効にする。
- 【IFTTT】レシピを作成する。



##【Teams】通知先チャネルでWebhookを有効にする。
Teamsを開き、通知先となるチャネルのミートボールメニューの中の「コネクタ」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/a25a1a11-3665-2612-64a2-1a7e387d1cdb.png)


コネクタ一覧が開くので、「Incomming webhook」を探して追加します。
![2021-05-12_15h47_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/ec330e1a-86ca-ae2e-73a7-4709d0531d10.png)

構成画面が開くので通知してくれるbotアカウントの①名前と②アイコン画像を設定します。
![2021-05-12_17h48_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/1c98120d-479c-5e93-026c-95268596552f.png)

作成ボタンを押すとpost先のurlが生成されます。IFTTTの設定で必要になるのでコピーしておきます。完了を押してTeamsの設定は終わりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/24fbd93b-1d4e-01e1-e7dc-2ab8ef8c398d.png)



##【IFTTT】レシピを作成する。
IFTTTにログイン⇒Createボタンをクリックします。
![2021-05-13_18h04_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/df0ba6d7-0878-5b8f-a918-05ab27d55eed.png)

「If This」をクリック⇒「Google Sheets」をクリックします。今回は新規行追加を通知のトリガーとするので「New row added to spreadsheet」をクリックします。（ほかにも「フォルダー内に新しいスプレッドシートが作成されたら」とか、「セルが更新されたら」などのトリガーがあるみたいですね。）
![2021-05-13_18h16_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/2bc482b3-c79a-b50c-207e-6238bb2bc121.png)

下図の赤枠のところ、スプレッドシートのURLを入力しCreate Triggerをクリックします。
![2021-05-13_18h18_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/dd344e3c-afb5-c07c-e9c9-b7651b6155b8.png)

「Then that」をクリック⇒「webhooks」⇒「Make a web request」をクリックします。
![2021-05-13_18h30_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/4fa412fe-06bf-af0c-21a8-c76150b618d2.png)

- URL
    - teamsの設定の時にコピーしたURLを入力します。
- Method
    - `POST`を選択します。
- ContentType
    - `JSON`を選択します。
- BODY
    - Teamsに通知されるメッセージ本文をJSON形式で入力します。「Add indegredient」というボタンを押せばスプレッドシートのデータを動的パラメータとして簡単メッセージに埋め込むことができます。
    - 今回はテストとして下記のメッセージを入力します。動的パラメータとして{{RowIndex}} を使います。
        - `{"text":"スプレッドシートに新しく行が追加されました。{{RowIndex}} 行目だよ。"}`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/f6d0ef00-33da-3dfa-79c6-8d40c09947af.png)


##テストしてみる。
下図のようにbotアカウントが通知してくれました。
![2021-05-13_19h15_27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342467/8069652c-be95-5310-3642-a105db822fec.png)




## エラーの時、躓いた時に確認すること
- IFTTTのレシピ作成が出来ない・・・。
    - レシピ作成数が上限かも。（トライアルアカウントだと3つまで。）IFがクリック出来ないときはコレの可能性大。既存のレシピを削除すべし。
- スプレッドシートを更新しているのに通知されない・・・。
    - IFTTTのレシピをクリック⇒Activity Logからログを確認して動作状況、エラー状況を確認しましょう。


# おわり
おしまい。
【Ansible】loop変数が空の文字列でもエラーにしない

### はじめに
<バージョン>
ansible 2.9.7
　以下のplaybookでは、変数（sample_list）の内容にもとづいてloopを実行するのですが、
loop変数が空の文字列だと、エラーが出てしまいます。

```yaml:loop_sample1.yml
---
- hosts: localhost
  gather_facts: false
  vars:
    sample_list: ''
  tasks:
    - name: loop_test
      debug:
        var: item
      loop: "{{ sample_list }}"
```

```text:エラー
msg: 'Invalid data passed to ''loop'', it requires a list, got this instead: .
Hint: If you passed a list/dict of just one element, try adding wantlist=True to your lookup invocation
 or use q/query instead of lookup.'
```

### 1. playbook紹介
　defaultフィルターは、指定した変数が宣言されていなかった場合の初期値を定義出来るのですが、
[フィルター — Ansible Documentation](https://docs.ansible.com/ansible/2.9_ja/user_guide/playbooks_filters.html#id32)に記載されているように、
2番目のパラメーターを true に設定すると、変数が false または空の文字列の場合に
デフォルト変数を使ってくれるようです。

```yaml:loop_sample2.yml
---
- hosts: localhost
  gather_facts: false
  vars:
    sample_list: ''
  tasks:
    - name: loop_test
      debug:
        var: item
      loop: "{{ sample_list | default([], true) }}"    # ポイント
```

### 関連記事
[フィルター — Ansible Documentation](https://docs.ansible.com/ansible/2.9_ja/user_guide/playbooks_filters.html#id32)
Microsoft Teams で Web 会議をするときの画面解像度の違いによるパソコンの負荷を観察してみた

**注意: この記事は個人的に試してみたらこうなったというものであり、その効果を保証するものではありません。**

突然ですがきっかけはこの記事。

https://docs.microsoft.com/ja-jp/microsoftteams/troubleshoot/known-issues/teams-slow-video-meetings-laptops-4k

Microsoft の Docs を眺めていたら目についたのですが、4K やら HDR やらの今どきなディスプレイを利用していると Web 会議中に Teams の処理速度が低下するというもの。ホントかいな。新しいものではなく昨年の夏ごろから公開されている情報みたいです。

回避策を見るとそのひとつに下記のようにあります。

> 4K または HDR モニターの解像度を一時的に 1920 x 1080 に変更します。

これならすぐに試せそうなのと、FullHD 以上で処理速度に影響するなら Surface Pro のような高解像度なノート PC でも影響があるんじゃないかと考え、こんな単純なことで効果があるんなら嬉しいなーと思ったのでさっそく効果を観察してみることにしました。

#観察してみる
実験機のスペックと Microsoft Teams の状態については次の通りです。Surface Pro 4 はバッテリーもへたってきていて、そろそろ新しいのに買い替えたいんですよね…。

- 実験機のパソコン
    - Surface Pro 4
    - CPU i5
    - Mem 8GB
    - 外付けディスプレイなし

- Microsoft Teams の状態
    - Web 会議ウィンドウを最大化表示
    - カメラを有効化し背景効果も利用
    - デスクトップ共有を利用
    - 他の参加者 1 名のカメラ映像を表示

##2736 x 1824
まずはいつもの解像度。僕はこの解像度で表示スケール 100% で使ってます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/38e8a50c-a8f5-c86c-1c4e-8e4e929e54c4.png)

パソコンの負荷はこんな感じ。まあまあ辛そうです。

##800 x 600
つぎは設定できる最小の解像度。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/3b3e2453-358c-26ed-e778-5062cd9cb5ac.png)

ひと目で負荷が軽くなりましたね。CPU と GPU に効果があるみたいです。パソコン全体の負荷もそうですが、Microsoft Teams の CPU 使用率も大きく下がっていますね。

##1920 x 1200
このサイズくらいなら使っても良いかなという解像度。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/3cfb29e0-7277-df86-702e-d61b00692926.png)

これでもいつもの解像度に比べると少し余裕がありそう。

##時間経過で観察
効果が大きい CPU の使用率のグラフで観てみると、解像度を 1920 x 1200 に下げた赤い点のところから明らかに使用率も下がっていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/fd6aec6e-c6ba-858b-fe01-76632bb70626.png)

これは効果が期待できそうです。

##表示スケールの変更は効果小
解像度ではなく表示スケール（100% とか 200% とか）を変更したらどうかなと試しましたが、効果はゼロではないものの解像度の変更のほうが効果が大きそうでした。

##解像度を下げた外付けディスプレイを用意
パソコンに解像度を下げた外付けディスプレイを用意して、Microsoft Teams の Web 会議ウィンドウをそちらに移すだけでも効果がありました。Web 会議用にほどほどのサイズの外付けディスプレイを用意しておくのも有効かもしれません。

##Microsoft Teams の Web 会議ウィンドウのサイズを小さく
いろいろ観察を続けていると、どうやら単純に Microsoft Teams の Web 会議ウィンドウの表示サイズに大きく影響されているようです。そのため、パソコンの解像度を変更しなくても、Web 会議ウィンドウの表示を小さくするだけでも効果がありそうでした。ただし、実際の利用シーンを考えるとウィンドウを小さくしていると肝心のコンテンツが見えないので、解像度を下げた外付けディスプレイを用意しておくのが良さそうです。

##ビデオの着信をオフにする
やっぱり CPU が多く使われる場面は、他の参加者のカメラ映像を映しているときみたいなので、カメラの表示が不要なときには「ビデオの着信をオフにする」を設定しておくと良さそうでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167110/2784c950-416b-aed7-62b6-ef4a26cea2cd.png)


#まとめ
というわけで、Microsoft Teams の Web 会議がちょっと重いなあというときは画面の解像度をちょっと変更してみると良いかもしれないということが観察結果からも分かりました。少なくとも高解像度のディスプレイに Web 会議のウィンドウを最大化表示するのはパソコンにかなり負荷をかけているみたいでした。そうした大きなディスプレイを利用するときには画面の解像度を下げておくと良さそうです。さっそく次回の Web 会議で試してみようっと。

Web 会議用に小さな外付けディスプレイを用意しておくのも良いなー。
Cannot declare class (クラス名), because the name is already in useの対策

```
(ファイル名) % php artisan migrate
```
を行うと

```
Cannot declare class AddGoogleIdColumn, because the name is already in use
```
というエラーが出ました。この内容としては、「そのクラス名宣言できませんよ。既に使われていますよ」とのことでした。
しかし、クラス名で検索しても他に重複は見つかリませんでした。調べてみるとnamespaceを変えると解決しましたという記事も見かけました。

#namespaceとは
>namespaceとは、PHPで名前空間（エイリアス）を設定するために使用されるものです。
 一般的にPHPフォルダーのはじめにnamespace <ファイルのパス>と記載します。
 エイリアスをファイルのパスにすることで自動読み込みを行うことができるようにしています。

#解決策
ファイル名でした！そのため以前のファイル名に復元させるとエラーは治りました！
```
% php artisan migrate:fresh
```
で、やってみるのもありだと思います。
【php】複数のデータセットを入力画面から作成する方法

```PHP
<?php

while ($data = trim(fgets(STDIN))) {
    $list[] = $data;
}
var_dump($list);
?>
```

入力

```
9 1 8 2
4 1 5 9
4 6 8 2
4 6 3 2
```

出力

```
array(4) {
  [0]=>
  string(7) "9 1 8 2"
  [1]=>
  string(7) "4 1 5 9"
  [2]=>
  string(7) "4 6 8 2"
  [3]=>
  string(7) "4 6 3 2"
}
```
Jetpack ComposeでURLから画像を取得する

# 利用するライブラリ
[Remote Image for Jetpack Compose](https://github.com/agarasul/RemoteImage)

URLを指定するだけでネットワークから簡単に画像を持ってくることができるJetpack Composeで利用できるライブラリです。

# 導入
プロジェクトレベルのbuild.gradle

```gradle:build.gradle
allprojects {
    repositories {
        ...
        maven { url 'https://dl.bintray.com/agarasul/RemoteImage' }
        ...
    }
}
```

アプリレベルのbuild.gradle

```gradle:build.gradle
dependencies {
    ...
    implementation 'dev.rasul:remoteimage:1.0.4'
    ...
}
```

# 使い方

```kotlin
RemoteImage(
    url = newsItem.urlToImage,
    contentScale = ContentScale.Crop,
    modifier = Modifier.height(200.dp),
    error = {
        Text(text = "Could not load image")
    },
    loading = {
        CircularProgressIndicator(
            strokeWidth = 2.dp,
            modifier = Modifier.size(16.dp)
        )
    }
)
```

url：取得したい画像のURL
contentScale：画像のスケールタイプ（ImageViewの[scaleType](https://developer.android.com/reference/android/widget/ImageView.ScaleType)と同じ）
modifier：高さや幅など、他の[modifier](https://foso.github.io/Jetpack-Compose-Playground/general/modifier/)と同様
error：エラー発生時に表示されるView、デフォルトではText
loading：画像のロード中に表示されるView、デフォルトでは[CircularProgressIndicator](https://foso.github.io/Jetpack-Compose-Playground/material/circularprogressindicator/)

# 参考リンク
[https://github.com/agarasul/RemoteImage](https://github.com/agarasul/RemoteImage)
新method追加

 member
「member」とは、「resources以外のメソッドを追加したい」且つ「id情報を伴うURIを生成したい」時に使用します。使い方は以下の通りです。

memberの使い方①

```rb
member do 
  HTTPメソッド  ‘アクション名’
end
```

ただ、追加したいアクションが1つだけの時は以下のように記述出来ます。

memberの使い方②

```rb
  HTTPメソッド  ‘アクション名’ , on:  :member
```

今回は「orderメソッド（購入機能のメソッド）」に対してmemberを使います。
それではルーティングを設定しましょう。

 ルーティングを設定しましょう
ルーティングを以下のように設定してください。

↓↓↓↓↓↓↓ あなたの記事の内容
```rb:config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  root to: "items#index"
  resources :items do
   resources :purchases, only: [:index, :create]
  end
end
───────
```rb:config/routes.rb
↑↑↑↑↑↑↑ 編集リクエストの内容

```

↓↓↓↓↓↓↓ あなたの記事の内容
───────
  # （省略）
↑↑↑↑↑↑↑ 編集リクエストの内容

↓↓↓↓↓↓↓ あなたの記事の内容

───────
  resources :cards, only: [:new, :create]
  resources :items, only: :order do
    post 'order', on: :member
  end
end
```
↑↑↑↑↑↑↑ 編集リクエストの内容
MinecraftでMODを開発したい#5

*MinecraftでMODの開発をします*
*試行錯誤を書いていくだけのものになります*

##概要
MODをjar形式にし、一般の人に配布して使えるように

##動作環境 2021/05/12
||Version|
|:-:|:-:|
|Mac OS Big Sur|11.1|
|IntelliJ IDEA|2021.1.1|
|AdoptOpenJDK (HotSpot)|1.8.0_282|
|Minecraft|1.16.5|
|Forge|36.1.0|

##目次
-　設定
-　確認


##設定
build.gradleのversionを1.16.5-1.0.0に変更
IntelliJ IDEAのGradle Tool Windowを開き、Tasks > build > buildをダブルクリックで実行

##確認
IntelliJ IDEAの画面下側に表示される実行ログに「BUILD SUCCESSFUL」と表示され、build/libs/にexamplemod-1.16.5-1.0.0.jarが生成されたことを確認してください。

他のMODを導入する時と同様に、jarファイルをMinecraftのmodsフォルダに入れてランチャーからMinecraftを起動
タイトル画面の「Mods」ボタンを押し、MOD一覧に「Titanium Mod」が表示されていることを確認
また、ワールドに入ってアイテム・ブロック・レシピが正しく追加されていることを確認

![スクリーンショット 2021-05-13 18.42.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482491/92b6d3e9-16b8-c33c-3472-33c540e8b716.png)
![スクリーンショット 2021-05-13 19.03.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482491/16f78ae6-5bab-e52c-5259-7760f083853d.png)
導入できていた



######参考文献
https://www.tntmodders.com/tutorial/build-1165