OmniAICreator/Qiita-1.07M huggingface dataset:
【PowerShell】cabファイルの作成と展開

# はじめに

仕事で初めて`.cab`形式のファイルを作る機会があったので、cabファイルの作成（圧縮）と展開の方法をまとめてみました。


# cabファイルの作成（圧縮）

## 1つのファイルの圧縮

* 1つのファイルをcab形式で圧縮する時は、`cab {圧縮するファイル名} {圧縮後のファイル名}`とコマンドを入力します。

```powershell:1つのファイルの圧縮
PS C:\Users\NKOJIMA\Documents\cabtest> makecab a.txt a.cab
Cabinet Maker - Lossless Data Compression Tool
```

```powershell:実行結果
PS C:\Users\NKOJIMA\Documents\cabtest2> tree /F ./
C:\USERS\NKOJIMA\DOCUMENTS\CABTEST2
    a.cab
    a.txt

サブフォルダーは存在しません
```

## 複数のファイルの圧縮

* 複数のファイルを圧縮する場合は、最初に圧縮するファイルを列挙した`.ddf`という形式のファイルを用意します。
 * [こちらのページ](https://unilab.gbb60166.jp/wininst/wininst.htm)を見ると、拡張子が`.ddf`でなくても正常に動作するようです。
* なお、「;」から始まる行はコメント行となります。

```text:cabtest.ddf
; cabtest.ddf
C:\Users\NKOJIMA\Documents\cabtest\a.txt
C:\Users\NKOJIMA\Documents\cabtest\b.txt
C:\Users\NKOJIMA\Documents\cabtest\c.txt
```

* 複数のファイルをcab形式で圧縮する時は、`cab /f {.ddfファイル名}`とコマンドを入力します。

```powershell:1つのファイルの圧縮
PS C:\Users\NKOJIMA\Documents\cabtest> makecab /f cabtest.ddf
Cabinet Maker - Lossless Data Compression Tool

101 bytes in 3 files
Total files:              3
Bytes before:           101
Bytes after:             23
After/Before:            22.77% compression
Time:                     0.01 seconds ( 0 hr  0 min  0.01 sec)
Throughput:               6.58 Kb/second
```

* 1つのファイルを圧縮した時と違い、自動生成された`disk1`というフォルダ内に`1.cab`という名前で圧縮ファイルが作られました。
 * `1.cab`を任意のファイル名で作る方法は分かりませんでした...
* また、`setup.inf`や`setup.rpt`などのファイルも自動生成されていました。
 * この2つのファイルはともに圧縮処理のログファイルでした。

```text:実行結果
PS C:\Users\NKOJIMA\Documents\cabtest> tree /F .\
C:\USERS\NKOJIMA\DOCUMENTS\CABTEST
│  a.txt
│  b.txt
│  c.txt
│  cabtest.ddf
│  setup.inf
│  setup.rpt
│
└─disk1
        1.cab
```


# cabファイルの展開（解凍）

* cab形式のファイルを展開する時は、`expand {圧縮ファイル名} {展開後のファイル名}`とコマンドを入力します。

```powershell:cabファイルの展開
PS C:\Users\NKOJIMA\Documents\cabtest> expand .\a.cab .\a.txt

.\a.txt を展開キューに追加しています

ファイルを解凍しています...

ファイルの解凍が完了しました...
```

* 複数のファイルから構成されているcab形式のファイルを展開する時は、`expand {圧縮ファイル名} /f:{展開するファイル} {展開先のフォルダ名}`とコマンドを入力します。
* `/f`パラメーターで指定する「展開するファイル」は、`*`または`?`をワイルドカードとして使えます。

```powershell:複数のファイルから成るcabファイルの展開
PS C:\Users\NKOJIMA\Documents\cabtest> expand .\1.cab /f:* .\test

.\test\a.txt を展開キューに追加しています
.\test\b.txt を展開キューに追加しています
.\test\c.txt を展開キューに追加しています

ファイルを解凍しています...

ファイルの解凍が完了しました...
合計 3 ファイル
```


# 参考URL

* [makecab - Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/makecab)
* [Windows Installer](https://unilab.gbb60166.jp/wininst/wininst.htm)
* [expand - Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/expand)
Whisperのlarge-v2がリリースされたので試してみた

Whisperのlarge-v2がこっそりリリースされたようです。こちらの論文（と解説動画）によると英語以外での精度が圧倒的に上がっているそうです。

https://www.youtube.com/watch?v=3nLrl2d5ndI&ab_channel=1littlecoder

# Whisper最新版のインストール
通常はこちらでインストールしますが
```
pip install git+https://github.com/openai/whisper.git 
```

最新版はこちらでインストールします（githubより）
```
pip install --upgrade --no-deps --force-reinstall git+https://github.com/openai/whisper.git
```

追加でffmpegも必要になったみたいですね。pip install ffmpegではなくffmpeg-pythonのほうをインストールする必要があります。
```
pip install ffmpeg-python
```

pip install ffmpegだとこちらのエラーが出ます。
https://stackoverflow.com/questions/73842876/fmpeg-has-no-attribute-input

# 実行
2.8GBのモデルがダウンロードされます。今のところはlarge-v2と指定します。将来的にはlargeで参照できるようになると書いてありますね。
```
import whisper
#model = whisper.load_model("small")
model = whisper.load_model("large-v2")
```

適当なYoutube動画から音声を取得して試してみます。
```
yt-dlp -x --audio-format mp3 https://youtu.be/hogehoge
```

ダウンロードされたmp3ファイルを指定してWhisperで書き起こします。
```
path = 'hogehoge.mp3'
result = model.transcribe(path, verbose=True, language='ja')
```

以前のバージョンと比較はしていないので精度についてはよくわからないですね。以前のバージョンでもかなりの精度が出てました。試したところ６０分以上の音声の連続書き起こしでもエラーにならないようです。
【15日目】discord.jsでシェルコマンドを作ってみよう

# はじめに
こんにちは、なりかくんです。
今回は、discord.jsでシェルコマンドを作ってみようと思います。

# コマンド実行にchild_process
今回は、`child_process`というライブラリを使ってNode.js上でシェルを実行させます。その中でもストリーム形式という非同期実行でリアルタイムに更新されるようにします。

以下のようなコードでシェルを動かすことが出来ます。
```js
const childProcess = require('child_process');
const ping = childProcess.spawn('ping google.com');

ping.stdout.on('data', (data) => {
    console.log(`stdout: ${data}`);
});

ping.stderr.on('data', (data) => {
    console.error(`stderr: ${data}`);
});

ping.on('close', (code) => {
    console.log(`Exited code: ${code}`);
});
```

ただしWindowsではこのままだと文字化けしてしまうのでエンコードします。以下のコードでエンコードできます。なお、`encoding-japanese`モジュールを使っています。
```js
const childProcess = require('child_process');
const encoding = require('encoding-japanese');

const ping = childProcess.spawn('ping google.com', { encoding: 'Shift_JIS' });

ping.stdout.on('data', (data) => {
    console.log(`stdout: ${toString(data)}`);
});

ping.stderr.on('data', (data) => {
    console.error(`stderr: ${toString(data)}`);
});

ping.on('close', (code) => {
    console.log(`Exited code: ${code}`);
});

const toString = (bytes) => {
    return encoding.convert(bytes, {
        from: 'SJIS',
        to: 'UNICODE',
        type: 'string',
    });
};
```

これで文字化けさせずに正常に表示させることが出来ます。

# コマンドにする
では、discord.jsでBotからコマンドを実行ようにコードを変えていきます。今回は、以下のようなコードを作りました。
```js:exec.js
const { SlashCommandBuilder } = require('discord.js');
const childProcess = require('child_process');
const encoding = require('encoding-japanese');

module.exports = {
	data: new SlashCommandBuilder()
		.setName('exec')
		.setDescription('コマンドを実行します')
		.addStringOption(option =>
			option.setName('cmd')
				.setDescription('コマンドを入力')
				.setRequired(true)),
	async execute(interaction) {
		let cmd = interaction.options.getString("cmd");
		await interaction.reply(`\`\`\`shell\n# ${cmd}\n\`\`\``);
		let stdMsg = await interaction.channel.send(`\`\`\`\n\`\`\``);
		const spawn = childProcess.spawn(cmd, { shell: true, timeout: 6000, encoding: 'Shift_JIS' });
		let stdout = [], stderr = [];
		spawn.stdout.on('data', async (data) => {
			stdout.push(toString(data));
			await stdMsg.edit(toMsg());
		});
		spawn.stderr.on('data', async (data) => {
			stderr.push(toString(data));
			await stdMsg.edit(toMsg());
		});
		spawn.on('close', (code) => {
			interaction.channel.send(`\`\`\`shell\n[CLOSE] Code: ${code}\n\`\`\``);
		});
		const toMsg = () => {
			return `\`\`\`shell${(stdout.length!=0?`\n[STDOUT]${stdout.join("")}`:"" + stderr.length!=0?`\n[STDERR]${stderr.join("")}`:"").substring(0, 1800)}\n\`\`\``;
		}
		const toString = (bytes) => {
			return encoding.convert(bytes, {
				from: 'SJIS',
				to: 'UNICODE',
				type: 'string',
			});
		};
	},
};
```
なお、出力部分に関してはDiscordの文字制限の都合以上、以下のようなコードで1800文字までに制限しています。
```js
String.substring(0, 1800)
```

実際に動作させてみるとこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/d6409306-83e5-1f45-d75a-f7dba4960b88.png)

正しく動いていますね。
このコマンドは権限などの設定を正しくしないと悪用されるので非常に注意が必要です。

以上です、最後までお読みいただきありがとうございました。
makeからunzipを呼び出すときの注意点

# makeからunzipを呼び出して起きた事件

Kaggleのタイタニックのデータの取得を自動化するために，以下のようなMakefileを書きました．
Kaggleから3つのcsvファイルが入ったzipファイルを取得して，それを解凍するだけです．

```makefile:Kaggleのタイタニックのデータの取得
TARGETS=gender_submission.csv test.csv train.csv
ZIP=titanic.zip

all: $(TARGETS)

clean:
        rm $(TARGETS) $(ZIP)

rebuild: clean
        make

$(ZIP):
        kaggle competitions download -c titanic

%.csv: $(ZIP)
        unzip $<
```

これでmakeしてみると...

```
# make
...
unzip titanic.zip
Archive:  titanic.zip
replace gender_submission.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
replace test.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
replace train.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
unzip titanic.zip
Archive:  titanic.zip
replace gender_submission.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
replace test.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
replace train.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
unzip titanic.zip
Archive:  titanic.zip
replace gender_submission.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
replace test.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
replace train.csv? [y]es, [n]o, [A]ll, [N]one, [r]ename: n
```

なんかめっちゃ質問される...

# 原因

これはunzipを一回呼び出せば3つのcsvファイルが全てそろうのに，makeの野郎がcsvの個数の分だけunzipを呼び出しやがることで起きます．
一回目のunzipで3つのcsvファイルがそろい，二回目以降のunzipは同名のファイルが既に存在しているために上書きするかどうか聞いてきます．

# 対策

unzipされたかどうかを示すファイル`.unzipped`を用意します．
`.unzipped`が存在すれば既にunzipされており，存在しなければまだunzipされていません．
これをターゲットのcsvファイルの依存関係に挟むことで，unzipの呼び出し回数を一回にできます．

```makefile:unzipが一回だけ呼び出されるmakefile
TARGETS=gender_submission.csv test.csv train.csv
UNZIPPED=.unzipped
ZIP=titanic.zip

all: $(TARGETS)

clean:
        rm $(TARGETS) $(ZIP)

rebuild: clean
        make

$(ZIP):
        kaggle competitions download -c titanic

$(UNZIPPED): $(ZIP)
        unzip $^
        touch $@

%.csv: $(UNZIPPED)
        :
```
ちょっとだけSymbolブロックチェーンを使ったスマホゲームを作った話

# はじめに

昔、ブロックチェーンゲームのハッカソンがありました。

こういうゲームを突貫で作って応募したのですが、

https://symbol-tank.netlify.app/

次回作を作ろうと思い立ちました。

それがこちらです。

https://play.google.com/store/apps/details?id=io.github.planethouki.SymbolTank

主に替えたのは、ゲーム性の部分です。

トランザクションが発生するとゲームイベントが起きるというアイディアについては踏襲しています。ですが、そのゲームイベントについては同じではありません。

こちらが参考動画になります。トランザクションが発生するとコーンが降ってきます。

https://youtube.com/shorts/9Ou8GZT13eg?feature=share

（実際はこんなに頻繁にトランザクション発生してないと思う）

# 機能有効化

ブロックチェーンとゲームの関わりはすごくライトな仕様なので、通常はブロックチェーン要素がオフになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/917cb46a-2e64-1e3c-58b9-c8806d596bc0.png)

このように設定画面から有効にしないといけません。

何の説明もないので、Symbol知らない人にはよくわからないUIになってしまいました。

# トランザクション発生するとコーンが落ちてくる

最初に出した動画の再掲です。

https://youtube.com/shorts/9Ou8GZT13eg?feature=share

トランザクションが大量に発生すると、大量のコーンが降ってくることになるので、コーンは一定時間で消えるようになってます。

# トランザクションがあまり発生しないのでブロック発生イベントを使う

実際にゲームをプレイしてみると、ほとんどトランザクションが無く、機能を忘れてしまうようなことが度々ありました。

なので、ブロックでも出るようにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/5e324762-22ac-121a-21d3-8ad9967dad0a.png)

なんか板チョコみたいなんですが、元の素材は木箱です。そこに立体的なテキストメッシュでブロック番号を表現しています。

アセットの関係でテキストがセンタリングできなかったのでちょと寄っています。

https://youtube.com/shorts/7v3sv9YtqMY


# ブロックチェーン接続周りイメージ図

ここまで機能の紹介だったので、技術的なことについても書いてみます。

ブロックチェーンとゲームの実装上の境界について、このような感じにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/2f2ad249-5591-3570-e453-d14e75b1bffa.png)

`BlockchainService`は、ゲームとして必要なブロックチェーンの処理を扱うようになっています。例えば、トランザクションやブロックの情報などです。

これにより、ブロックチェーンSDKなどのライブラリ側の実装とは分離し、これについて意識しなくていいようにしました。

また`BlockchainService`は、イベントのみを扱うようになっており、他のクラスから受け取った通知を別のクラスに渡すような役割をしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/77f0bdca-4218-3531-790c-42f1da88369e.png)

そして、実際にSymbolブロックチェーンにアクセスするのは、`SymbolService`クラスです。

ここで、`ISymbolService`というインターフェース経由としているのは、実態となるクラスを切り替えられるようにするためです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172833/faaac282-a279-b412-3493-e7d44e09174a.png)

開発時には好きなタイミングでブロックやトランザクションを発生させた風に見せたり、本番では実際にブロックチェーンノードにアクセスしておく、ということをするためです。

# おわりに

簡単にゲームの紹介をしました。

ブロックチェーンを参照しているだけですが、プレイしてみると、あ、いまトランザクションが発生したんだな、ということが意識できるかと思います。

秘密鍵を保持したり、署名を作成したりトランザクションを送信しないので、実装も軽いです。

ぜひ、こういうライトな感じ気軽にゲームやアプリを作ってみてはいかがでしょうか。
ESモジュール版Reactを試してみた

[skypack.dev](https://cdn.skypack.dev)が提供する、[ESモジュール版React](https://cdn.skypack.dev/react)を利用すると、ブラウザから動的にReactモジュールを読み込んで表示することができます。

React公式ページ[既存のウェブサイトに React を追加する](https://ja.reactjs.org/docs/add-react-to-a-website.html)の手順でも同じことができますが、
Reactの機能がグローバルに公開されているのが気になるのでESモジュール版を利用した手順を作成しました。


### 特徴
* htmlファイル単独でReactを実行することができます
* 単独のhtmlファイルに記載してあるので、エクスプローラーからダブルクリックで実行できます(httpサーバはなくても動きます)
* jsxが使えないので、あまり実用的ではないです・・・(トランスパイルしていないので)
  * ⇒[babel-standalone](https://babeljs.io/docs/en/babel-standalone)で動的にトランスパイルするコードもつけました

### ①ボタンをクリックするとカウントアップするサンプル

よくあるごく簡単なサンプルプログラムが、htmlファイル単独で動くようになりました。


![img1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/d29bfb85-0584-4214-8c77-5b3d2436214e.png)


```html
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <title>React jsx-esm-standalone</title>
  <script type="module">
    // CDN経由でReactを読み込む(ESModuleであればブラウザから直接利用可能)
    import React, { useState } from "https://cdn.skypack.dev/react";
    import ReactDOM from "https://cdn.skypack.dev/react-dom";

    const Counter = () => {
      const [count, setCount] = useState(0);
      const handleClick = () => setCount((n) => n + 1);
      return (
        // jsxが使えないのでReact.createElement()を直接呼び出す
        React.createElement(React.Fragment, null,
          React.createElement("div", null, "Count: ", count),
          React.createElement("button", {onClick: handleClick}, "Increment"))
      );
    };
    ReactDOM.render(React.createElement(Counter), document.getElementById('app'));
  </script>
</head>
<body>
  <div id="app"></div>
</body>
</html>
```

### ②jsxを使えるように[babel-standalone](https://babeljs.io/docs/en/babel-standalone)で動的にトランスパイルする

&lt;script&gt;タグの中身を.jsファイルに分離して、トランスパイルするのが面倒なので
[babel-standalone](https://babeljs.io/docs/en/babel-standalone)を利用して、htmlファイル内でjsxを利用できるように変更します。

```html
<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <title>React jsx-esm-standalone</title>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <!-- @babel/standaloneでESModuleを利用するために、data-type="module"を追加 -->
  <script type="text/babel" data-type="module">
    // CDN経由でReactを読み込む(ESModuleであればブラウザから直接利用可能)
    import React, { useState } from "https://cdn.skypack.dev/react";
    import ReactDOM from "https://cdn.skypack.dev/react-dom";

    const Counter = () => {
      const [count, setCount] = useState(0);
      const handleClick = () => setCount((n) => n + 1);
      return (
        <>
          <div>Count: {count}</div>
          <button onClick={handleClick}>Increment</button>
        </>
      );
    };
    ReactDOM.render(<Counter />, document.getElementById('app'));
  </script>
</head>
<body>
  <div id="app"></div>
</body>
</html>
```
（備忘録）Lenovo IdeaPad Duet 350i で Linux USB ブートする方法

（備忘録）Ubuntuインストール簡易手順

# 1. はじめに
今回は、自分自身への備忘録を兼ねて、Lenovo IdeaPad Duet 350i で Linux USB ブートする方法を、お伝えしたいと思います

- 参考文献：[YouTube：2010年の古いPCが、USB 起動 Linuxで生まれ変わる](https://youtu.be/U5oZJGwgB3Q)

# 2. この記事を読んでできること
- Lenovo IdeaPad Duet 350i で Linux USB ブートすることができるようになる

# 3. 注意事項
-使用するUSBメディアや、LinuxOSの種類によってはUSBブートできない場合もあります
- USBブートに成功した場合でもディスプレイ表示が回転しているなどの症状が出る場合があります（画面がタブレット縦持ち表示となる）

# 4. 必要なもの
- Lenovo IdeaPad Duet 350i
- LinuxUSBブートメディア（Manjaro Linuxを利用）

# 5. BIOS画面の起動
- 電源を入れた直後に、Fnキー＋F2キーを押下し、BIOSメニューを表示する

# 6. セキュアブートを無効
- セキュブート設定を「Disable（無効）」に変更し、BIOS設定を保存しBIOS画面を終了する

```plaintext:BIOS操作
Start Menu
  Security
    → Secure Boot
      → Disabled

  Exit
    → Exit Saving Changes

```

# 7. ブートメニューの表示
- 電源を入れた直後に、Fnキー＋Fn12キーを押下しブートメニューを表示し、該当のUSBメディア（Linux USBメディア）を選択し、Linux OSを起動する

# 8. 起動実績の紹介
- Manjaro Linux のUSBメディアを使って検証したところ、みごとOS起動に成功しました
- ただし、ディスプレイが90度回転しており、またスピーカーの音がでない症状がありました
- ディスプレイの回転は、ディスプレイ設定から正位置に戻すことで問題を解決することができました
- スピーカーの音は問題の解決までにはいたらず、もしかするとHDMI出力側か、3.5ミリジャック側に音がとられていたかもしれません（未検証）
- その他、キーボード、タッチパッド、ディスプレイタッチパネルは問題なく動作していました
- Manjaro以外にも、ChromiunOSや、UbuntuOSも試しましたが、こちらは起動中の黒い画面から進展なく正常起動させることができませんでした（もしかしら、USBメディアを変えたり、OSバージョンを変えることで改善できるかもしれません）
- その後、元々のWindows10の起動を確認しましたが、問題なく起動、動作することを確認済みです

※後日確認したところ、スピーカーの音は問題なく出力されていることを確認いたしました（2022/12/23）

# 9. おわりに
いかがでしたでしょうか？Lenovo IdeaPad Duet 350i で Linux USB ブートすることができたのではないかと思います
今回の記事が、みなさまの学習の参考になれば幸いです

2022/12/17 TAKAHIRO NISHIZONO
flutter_launcher_iconsでandroidとiosのアプリアイコンを登録する

# flutterパッケージ
最近flutterを使っており、なかなか使い勝手が良いと思えてきました。flutterはいろんなパッケージを利用して機能拡張できますが、中でも便利だなと思ったパッケージについて、備忘も兼ねてまとめました。
ちなみに、パッケージとプラグインの違いがわかってなかったのですが、flutterでのパッケージとは「pubspecファイルを含むディレクトリのこと」で、プラグインとはパッケージの一種で「プラットフォームで固有の機能をFlutterアプリに提供するようなパッケージのこと」らしいです。知らずにいると恥ずかしい思いをしそうなのでメモっておきます。

https://minpro.net/difference-between-package-and-plugin

## パッケージを使ってアプリアイコンを登録
開発を終えアプリをリリースする段階になると、アプリアイコンを用意すると思います。従来の開発環境だと画素数ごとにアイコンを用意したり、osごとに対応したアイコンを用意したりと、なかなか手間がかかる作業だったと記憶してます。
ですが、flutter_launcher_iconsというパッケージを使ったところ、ベースとなるアイコンを用意するだけで、画素数に対応したアプリアイコンを作成してくれ、さらにはandoridのアダプティブアイコンにも対応してくれているので、格段にアイコンの管理が楽になりました。

## アイコンの準備
アプリアイコンは１つでも良いですが、アダプティブアイコンを使う場合はios/android用にそれぞれ１つずつ用意します。

https://note.com/designswitch/n/n1d8e34c5ad8c

## パッケージのインストール
flutter_launcher_iconsパッケージを使える状態にします。
pubspec.yamlに以下を追記します。

```
dependencies:
  flutter_launcher_icons: ^0.11.0

flutter_icons:
  android: true
  ios: 'AppIcon'
  image_path: 'assets/images/AppIcon.png'
  adaptive_icon_background: '##46B4EB'
  adaptive_icon_foreground: 'assets/images/AdaptiveIcon.png'

```
**flutter_icons:**
設定項目について以下補足

**android:**
android用にアプリアイコンを作成する場合「true」とします。
コマンド実行時、android/app/src/main/res/mipmap-xxxxフォルダに画像ファイルが出力されます。
※Android 8.0（API レベル 26）以降のみサポートする場合はこの項目は不要です。
**ios:**
ios用にアプリアイコンを作成する場合、ここにフォルダ名を指定すると
ios/Runner/Assets.xcassets/フォルダ名.appiconsetに画像ファイルが出力されます。
このとき<フォルダ名.appiconset>がないとエラーになるので、先にこのフォルダを作成しておきます。
※ここでフォルダを作成しておくと、Contents.json（画像の対応ファイル）も自動作成してくれるのでありがたい
**image_path:**
アプリアイコンの元となる画像ファイルのパスを記載します。
**adaptive_icon_background:**
アダプティブアイコンを使用する場合、背景色を指定します。
**adaptive_icon_foreground:**
アダプティブアイコンを使用する場合、元となる画像ファイルのパスを記載します。

## 元画像の配置とアイコン作成
pubspec.yamlの以下に指定したファイルパスの場所にそれぞれの画像ファイルを配置し、
- image_path:
- adaptive_icon_foreground:

対象パッケージのプロジェクトフォルダ直下で、以下のコマンドを実行します。

```
flutter pub get
flutter pub run flutter_launcher_icons:main
```

## 画像ファイルの最終調整
ここまでの手順で各解像度に対応した画像ファイルが一通り出力されます。
iosの画像ファイルで警告が出る場合があるので、そのときはXcodeで対象フォルダ（今回だとios/Runner/Assets.xcassets/フォルダ名.appiconset）を開き、ドラッグアンドドロップで画像ファイルを再配置すれば、警告は解消されます。
また、プロジェクト等でデザイナーさんが解像度ごとに画像ファイルを用意してくれる場合もあると思うので、その際は用意された画像ファイルを再配置すれば問題ありません。

## 最後に
flutter便利ですね。今後も使っていくので、また面白そうなパッケージなどあれば、紹介していきたいと思います。今回初投稿ですが、後々手順を思い出しつつ書いていくのは結構大変だなと思いました。同じ手順をやってみたり、ファイルパスを思い出せず１から調べ直したり、結局二度手間になり、かなり効率が悪かった。今更ですが、今後はこのような記事を書く前提で手順を残していこうかなと。
JS コード 短縮 [検索]

# ワンライナー化
## 処理;処理;
一文で表現できる処理はカッコとカンマを使って一文にまとめることができる
forやbreakなどの処理を使っている場合はmap等のメソッドに置き換えるか諦める必要がある
```js
let x=2;
x=x*x;
x=8-x;
console.log(x);
// ↓↓↓
let x=2;
(x*=x,console.log(x=8-x));
```
jsは実行する関数と渡そうとしている引数の数が合わない場合でも実行される
関数の受け取る引数が多いとundefinedが入るのでデフォルト引数を使って追加の変数の宣言ができる
関数に渡す引数が多いとカッコをとカンマを使ったワンライナー化とほぼ同じだが引数は渡される状態になる

## let
前述の(,,)の中では変数の宣言ができない
しかし即時関数を利用すれば変数の宣言が可能である
実行時に引数の受け渡しが難しい(mapの中など)場合は引数が渡されない範囲でデフォルト引数を利用すれば同様のことが可能である
```js
let x=2;
(x*=x,console.log(x=8-x));
// ↓↓↓
(x=>(x*=x,console.log(x=8-x)))(2);
//or
((x=2)=>(x*=x,console.log(x=8-x)))();
```

## if文
jsの論理演算子は先に全て実行してから評価では無く実行と評価を繰り返すので置き換えが可能である
elseも用いる場合は三項演算子が良い

```js
if(true)say(nyan);
// ↓↓↓
true&&say(nyan);

if(!true)say(nyan);
// ↓↓↓
true||say(nyan);

if(true)say(nyan);else say(nya);
// ↓↓↓
true?say(nyan):say(nya);
// ↓↓↓
say(true?nyan:nya);
```
## 配列を操作するループ
.reduce()でほとんどのループは置換できる
ちなみにmapやeachなど配列のメソッドはいろいろあるが全てreduceで表現できる
複数のループ系メソッドを繋げている場合はほとんどの場合reduce一本にまとめられるのでよく考える
if(x)break;fx();はx||fx();に置き換える
breakがないプログラムの方が実行速度は劣るが読みやすい(と思っている)
シェーダーを書いていた人間なので各ループの中の実行時間は近いほうが望ましいと思っているが実際どうなの?

```js
let arr=[1,2,3,4,5],
result=0;
for(let i=0;i<arr.length;i++)result+=arr[i];
// ↓↓↓
let arr=[1,2,3,4,5],
result=arr.reduce((a,x,i)=>a+x,0);
```
initial valueをObjectにすることで複数の値を格納できて便利

特定の回数回したいループの場合は長さのある空配列を用いると良い
```js
[...Array(3)]
// >>[undefined,undefined,undefined]
```
## オブジェクトを操作するループ
Object.entries()を使って配列に変換して操作する
操作が終わったらObject.fromEntries()でオブジェクトに戻す
Object.fromEntries(arr)はarr.reduce((a,x)=>(a[x[0]]=x[1],a),{})の方が速い
そもそもfromEntriesしたい場面においてentriesな配列に変換してから投げることが多いのでそれをするならreduceした方が良い

## switch文
```js
switch(x){
    case 'a':console.log('aだね');break;
    case 'b':console.log('bだね');break;
    case 'c':console.log('cだね');break;
    default:console.log('あ〜あ お前のせいです')break;
}
// ↓↓↓
({
    a:()=>console.log('aだね'),
    b:()=>console.log('bだね'),
    c:()=>console.log('cだね')
}[x]||(()=>console.log('あ〜あ お前のせいです')))();
```
オブジェクトは三項演算子とスプレッド演算子を使って一部の要素のみ切り替えることも可能なのでswitchよりも強力

# その他
## Math.floor
正確にはfloorではなくてtrunc
ビットor演算は数を整数に変換する
```js
Math.trunc(x);
// ↓↓↓
x|0
```
実行速度に関しては
ビットorは32bit整数への変換が挟まるのでMath.truncよりも遅いと思われる

## x==-1
正確にはx|0==-1
ビットnot演算子は-1のときに0を返すのでこれを利用する
indexOf()が-1を返したときの検出などに便利
```js
(x==-1)==!~x;
```

## undefined
voidが常にundefinedを返すことを利用
```js
undefined===void 0
```

## booleanな配列
bool型の入った短い(length<32)配列はビット演算子を使った使ったものに置き換えられる

## 変数名のつけ方???
人力minifyしまくると変数名というより引数名になる点はさておき
forEach,map,filter等(各要素,添字,元配列)な引数は外側から
```
(x,i)
(y,j)
(z,k)
```
の順で使う
このペアはずらして使うべきではない
reduceの場合は(a,x,i),(b,y,j)とか
reduceの中でreduceしたい場面が発生することはあまりない

元配列についてはほとんど使う場面がない
使いたい状況が発生している時点で使っているメソッドが適していない可能性がある
使うとすれば全体の長さの把握程度であってその場合は
```
(x,i,{length:l})
```

x,y,z,i,j,kは引数用にとっておきたいので
一番外側の関数の引数など大本になるオブジェクトを入れる場合はwを使う

グローバルに置きたくない場合はさらにオブジェクトでくるんであげるといいかも
個人的にはdとかqとかをよく使う
python numpy types

```python
from numba import types
from numba.typed import Dict

Dict.empty(key_type=types.unicode_type,value_type=types.uint64)
Dict.empty(key_type=types.unicode_type,value_type=types.float32[:, :])

Dict[np.unicode_(s)] = np.uint64(1)

listN = np.unicode_(list(df.name.values))

arr = v[:,3]
v = np.c_[v, v1]
np.float32(0.1)

a = np.empty(0)
a = np.append(a, v)
```
認証にトークンを利用する API の単体テストを書く

この記事は [Django Advent Calendar 2022 - Qiita](https://qiita.com/advent-calendar/2022/django) の 12/18 の記事です。

## 前提

- Django REST Framework を利用していることを前提とします
- JWT で認証する API のことを書きますが、JWT についてや JWT をどのように作るかについては触れません

## JWT で認証する API を作成する

JWT トークンを認証に利用する Web API のエンドポイントを書いた。

このアプリは Django を利用しているが、 `django.contrib.auth` のユーザーモデルを利用していない。そのため、ローカルで立ち上げて動かす分には JWT を Authorization ヘッダーに載せてしまえばよい。こんなふうに。

```sh
curl -H 'Authorization: Bearer ${JWT_TOKEN}' https://example.com/api/foobar
```

認証クラスは自作した、JWT をデコードして一意のユーザーID(uuid形式)を取得し、DB にユーザーが存在することを問い合わせるものである。

```python
from rest_framework.authentication import BaseAuthentication
from .models import User  # NOTE: django.contrib.auth.models.User **ではない**
class CustomAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # JWT の扱いはあまり書きたいことと関係ないので省略する
        jwt_string = ...  
        payload = ... # JWT の payload を取りだす
        user_id = payload["sub"]
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExists:
            return None

        return (user, None)
```

このクラスを view クラスの `authentication_classes` に指定した。そして無事、上記の curl コマンドで作った HTTP リクエストが動いた。

## 単体テストを書く

しかし、単体テストのときに困った。自分で定義したユーザーのため、force_login が使えないのだ。

```python
from django.test import TestCase, Client
from .models import User

class TestUseApi(TestCase):

    def setUp(self):
        self.u = ... # テスト用ユーザー準備

    def test_get(self):
        c = Client()
        c.force_login(self.u)  # auth_user のモデルを使っていないので動かない
        res = c.get('/api/foobar')
        self.assertEqual(res.status_code ,200)
```

困ったが、対処方法は別に難しくない。要するに token がないことが問題なので token を渡すようにカスタマイズすればよい。

Client オブジェクトに `login_with_token` メソッドを定義しその場で生成したトークンをヘッダーに載せる。

```python
from django.test import TestCase, Client

# test.py の Client をカスタマイズする
class CustomClient(Client):
    def __init__(self, enforce_csrf_checks=False, raise_request_exception=True, **defaults):
        self.user_id = None
        super().__init__(enforce_csrf_checks, raise_request_exception, **defaults)

    def login_with_token(self, user_id: str):
        self.user_id = user_id

    def request(self, **request):

        if self.user_id:
            request.update(
                {
                    "HTTP_AUTHORIZATION": f'Bearer {generate_jwt(self.user_id)}',  # ここで JWT トークンを生成する
                }
            )
        return super().request(**request)

class TestUseApi(TestCase):

    def setUp(self):
        self.u = ... # テスト用ユーザー準備

    def test_get(self):
        c = CustomClient()
        c.login_with_token(self.u.id)  # トークンを生成するユーザーの id を指定
        res = c.get('/api/foobar')
        self.assertEqual(res.status_code ,200)

        j = res.json()
        self.assertEqual(len(j), 1)
```

これでテストができた。

## まとめ

単体テストでも HTTP の Authorization ヘッダーにトークンを載せたいときは、 Client オブジェクトをカスタマイズして request を送る前にトークンをヘッダーに載せればいい。
マウスでファイルを選択・移動するのって面倒じゃない？

# 脱GUI！！！

筆者のメイン使用のPCはMacなのだが, ファイルへのアクセスを行う際はCUIでディレクトリを移動し直接コマンドを叩くことで, ファイルを呼び出している.

理由は, マウスでFinderを開いてフォルダをクリックするという動作を省くことが出来るため
**早くて楽だからである！！！**



だが, こう思う人もいるのではないだろうか.

わざわざ, [cd] で入力を行う方が面倒だと.

そこで, 今回はそれをショートカットする方法およびCUIでの便利設定を紹介したいと思う.

## 環境

Mac M1 Pro Ventura

## 移動ショットカットコマンドの実装

今回, 紹介する方法を実装することでコマンド[c]をターミナルに入力すれば, cdで移動した履歴を参照し, ディレクトリを移動することが可能になる.

### 事前インストール

brewをインストールしていない場合は下記コマンドを実行する.

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

ディレクトリを移動するためのfuzzy finder 通称[fzf]をインストールする. 詳細は, 下記のドキュメントを参考に.

    git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf
    ~/.fzf/install

https://github.com/junegunn/fzf#installation

インストール完了後, .zshrｃに下記を追加で記載する. なお, これは[サイト](https://qiita.com/shinshin86/items/b7e5d03135eef82df25b)を参考にさせていただいている.

~~~:.zshrc
function chpwd() {
  powered_cd_add_log
}

function powered_cd_add_log() {
  local i=0
  cat ~/.powered_cd.log | while read line; do
    (( i++ ))
    if [ i = 30 ]; then
      sed -i -e "30,30d" ~/.powered_cd.log
    elif [ "$line" = "$PWD" ]; then
      sed -i -e "${i},${i}d" ~/.powered_cd.log
    fi
  done
  echo "$PWD" >> ~/.powered_cd.log
}

function powered_cd() {
  if [ $# = 0 ]; then
    cd $(gtac ~/.powered_cd.log | fzf)
  elif [ $# = 1 ]; then
    cd $1
  else
    echo "powered_cd: too many arguments"
  fi
}

_powered_cd() {
  _files -/
}

compdef _powered_cd powered_cd

[ -e ~/.powered_cd.log ] || touch ~/.powered_cd.log

alias c="powered_cd"
~~~

追加後, 下記コマンドを実行し, Terminal上で[c]を入力, Enterを押すとcd履歴から参照されたものが表示される. さらに, それは十字キーで選択可能なので, 選択することで指定したディレクトリに直接移動することが出来る.

    source .zshrc

## ファイル 編集・閲覧方法

移動ショートカットについては上記の方法で可能になった.

では, 次はファイルを開く方法や閲覧方法について説明していく. 

### ディレクトリの中身を確認

ディレクトリの中身を確認するためのコマンドは[ls]で確認出来る. 他にも, 権限などを[ls -l]で確認出来たりもするので是非, 活用して欲しい.

### ファイルを開く

Terminalから直接ファイルを開く方法は, openコマンドで可能である. 例えば, PDFやtxtといった直接見るものをAdobe RenderやMac標準搭載のテキストエディターで見ることが出来る. なお, 大概のマウスクリックで開くものは開くことが出来る.

    open <開きたいファイル>

### VsCodeで開く

また, 移動したディレクトリをVsCodeで直接開くことも可能である. これにはよく使用する方法として, 2種類存在しており, １つが直接ファイルを指定する方法, もう一つがディレクトリの全てのファイルを開く方法である. 

指定

    code <開きたいディレクトリ>

全て

    code .

### 編集方法

また, ファイルを直接編集したい場合も存在する. 大概のものは, VsCodeで開き, 編集を行ったほうが早いが１つのファイルの中の一部分を変更する場合は, わざわざVsCodeを開くことが面倒に感じることもある. その場合には, 下記のコマンドで編集すれば良い.

#### nano

nanoエディターはシンプルな操作で, 使用することが出来る. 覚えておくべき項目は, 編集完了後はCtl+xを行い, 名前の変更がなければ[y]を行い保存する. これだけで良い.

    nano <編集したいディレクトリ>


#### Vim

Vimは, nanoでコードを探すのが面倒な時に使用している. 覚えておくべき項目は, :+iで編集可能, /で検索, :+qw!で強制保存. 大概は, ３つのコマンドを抑えておけば困らない.

    vim <編集したいディレクトリ>

## クラウドと連携することも可能

自身のPC内で, Google DriveやOne Driveなどをマウントしておけば[cd]コマンドで移動することが可能になる. そのため, 上記の方法でファイルを開いたり, 編集したりすることが可能になる.

## 最後に

初めは, マウス操作の方が良いと思うかもしれないが慣れるとterminal操作が楽になってくるはずである.

是非, Terminalでの快適な生活を送ってみてほしい.
#8 remote: Write access to repository not granted.が出た際の対処法

今回、2週間ぶりにpushしたらタイトルのエラーとなりPushが出来ませんでした。

いろいろなブログをみても3日間は解決方法が見出せず、正直まだ原因が曖昧です。

ただ、いろいろなURLを拝見し、Pushできたので備忘録として残します。

# 目次

1. エラーコード
1. 解決方法
1. 他に試したこと
1. 最後に

# 1. エラーコード

今回、当方の環境と、エラーコードです。

2週間Pushしなかったら、下記コードが出ました。

裏を返せば、セキュリティ対策がきちんとされていて安心ですね！

**◆環境**
Gitバージョン：2.37.3
エディタ：Visual Studio
OS：MacOS Ventura　13.0.1

```
 % git push origin master
Username for 'https://github.com': 〇〇（Username）
Password for 'https://〇〇（Username）@github.com':
remote: Write access to repository not granted.
fatal: unable to access 'https://github.com/〇〇（Username）/(repository).git/': The requested URL returned error: 403
```
403なので権限がないことを意味しています。

# 2. 解決方法

お困りの方もいらっしゃると思うので、先に解決につながったと思うことを羅列します。

a. SSHで接続
b. GithubにSSHキーを登録
c. SSH接続のテスト
d. コマンド実施


### a.SSHで接続
SSH設定は下記２つのURLを実施しました。

まず、新しいSSH キーを生成してssh-agentに追加しました。

下記、URLにアクセスすると、既存のSSHキーを確認があります。

既存のSSHキーを使う方法もありますが、私は新しいキーを作成しました。

なお、下記URLに書いている手順のままSSHキー作成を行いました。

https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent

URLに記載の③に記載の「プロンプトで、安全なパスフレーズを入力します」がPUSHする際に必要なパスワードなので**書き留めた方がいいです！**

### b.GithubにSSHキーを登録

次に、GitHubにSSHキーを追加します。

下記URLに書いている手順のままSSHキー追加を行いました。

なお、Githubに入れる際

- タイトル：当日の日付とSSHキーであること（何でも大丈夫です）
- キー：　`pbcopy < ~/.ssh/id_ed25519.pub`でコピーされているので、ペーストする

だけでした。

https://docs.github.com/en/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account

### c.SSH接続のテスト

心配だったので、テストもしています。

https://docs.github.com/en/authentication/connecting-to-github-with-ssh/testing-your-ssh-connection

### d.コマンド実施

行ったコマンドは大きく２つです。

*1.SETURLを変える*

`git config remote.origin.url`

で`https://github.com/(Username)/(repository)`と設定されていることを確認し、、、

`% git remote set-url origin git@github.com:(Username)/(repository).git`

で設定しなおしました。

> 参考:https://qiita.com/shizuma/items/2b2f873a0034839e47ce

*2.Pushし設定したSSHキーを入れる*
pushして、SSHキーを入れなさいとでてくるので設定したパスワードを入力しました。

`git push origin master`

`Enter passphrase for key '/Users/自身のPC/.ssh/id_ed25519': `


# 3. 他に試したこと
## 個人用アクセストークンの作成

Githubを参照し、トークン設定しました。

過去登録した際は、この方法でPUSHできましたが、、、今回はSSH接続でしかできませんでした。

https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

なお、Githubは少しわかりづらいかもなのでこちらも。

https://zenn.dev/yuri0427/articles/9587ae6a578ee9

# 4. 最後に
SSH接続でやっとPush出来ましたが、何が原因だったのかはちょっと本当にわかっていません。

今後Pushする際にパスワードを求めてくるので、、、。

その解決方法も分かりましたら追記します。
クラウド上でActive Directoryを実現する方法をまとめてみた

# はじめに
BeeXのインサイドセールス田中です。
1年前のクリスマスシーズンに記事を投稿してからあっという間に1年経ってしまいました…:sweat_smile:
久しぶりのQiita執筆です。
今回は、クラウド上でActive Directoryを実現する方法について情報をまとめたいと思います。
今年1年、オンプレミス上のActive Directoryをクラウドに移行したいというご相談をいくつか頂きました。
ご提案の過程で調べた情報がありますので、そちらを記事にまとめたいと思います:writing_hand:
技術的な内容というよりは、営業目線でそれぞれ移行方法の違いを説明する内容となります:bow:

# Active Directoryとはなにか？

Active Directory は、WindowsServerに搭載されている機能の1つです。
会社や組織のネットワーク上で「このユーザーは誰なのか？」という認証とアクセス制御を行うことができます。
例えば、一部の人にしかアクセスしてほしくない機密情報へのアクセス制限や複合機やサーバといったリソースへのアクセス制御があげられます。

# Active Directoryをクラウドで実現する方法

私が調べたところによると、Active Directoryをクラウド上で実現する方法は、4つありました。
もしこんな方法もあるよ！という場合は、こっそり教えてください:pray:

## AWS上で実現する方法
(1)  EC2上にActive Directoryサーバを構築する方法
(2)  マネージドサービス「AWS Directory Service」を使う方法：Simple AD
(3)  マネージドサービス「AWS Directory Service」を使う方法：Managed Microsoft AD

## Azure上で実現する方法
(4)  Azure Active Directoryを使う方法

# それぞれの方法を比較してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1818929/46cfc5d7-c4a2-44a6-6665-96695061e8c2.png)



実際にはActive Directoryでお客様が実現している内容をヒアリングした上でどの方法が最適なのかをアドバイスしたり、提案したりすると思いますので、比較ポイントはもっと技術寄りの内容で多く存在すると思います。
今回はまずは、「ＡＤサーバクラウドに移行したいけど、どんな方法があるの？」と聞かれたときにこんな情報をまずは出せたら会話が膨らむかな？という視点で情報をまとめてみました！

# 最後に

社内リソースの管理もADサーバで実施している場合など、ADサーバをクラウド化するのは簡単ではないんだと思いました。
営業目線だと、何でも「クラウド移行しませんか？」から入ってしまうことが多いのですが、お客様の状況や環境を知ったうえで、
移行できるもの/移行できないもの、工夫すれば移行できるもの等々、切り分けてご提案できるようになりたいです。
特にインサイドセールスは、当社とまだお取引がないお客様と商談をさせて頂く機会が多いので、当社のことを知ってもらうよりもまずは、私がお客様のことを深く理解できるように会話のベースとなる知識や知見の習得に日々励みたいと思います:muscle:
Vue.jsでCompositionAPIを使わなくていい理由と、それでも理解しなければならない理由

本記事は [Vueのカレンダー \| Advent Calendar 2022 \- Qiita](https://qiita.com/advent-calendar/2022/vue) の17日目の記事です。

まぁポエムみたいな記事なんですが。


## Vue3 とComposition API

Vue3にComposition APIという新しいコンポーネントのインターフェースが登場しました。
これにより、コードをピュアなJSとして扱うことができ、型付がより便利になったりコードの分割を可能にします。


## で、あなたにComposition APIは必要なのか

「せっかくVue3に挑戦するんだし、Composition APIで書きたいよね〜」と思っているみなさん、9割くらいはその必要はないと私は思っています。

なぜなら、「CompositionAPIでできることは基本的に増えない」「（コードベースが大きくならない限りは）一つのファイルにあるほうがまとまってて見やすい」「というかrefとかreactiveとか認知負荷が大きい」というものです。

Composition APIを使う必要があるのは、コードが大きくて見づらいんじゃい！とか整理したくなったとか、コンポーネントのロジックを再利用したくなったときだけで十分でしょう。

Composition APIでやってみたけどよくわかんねー！ハマった！もう嫌だ！ってなる前に、Options APIで書き直してみるという選択肢を忘れないでください。

Options APIのほうが歴史的にドキュメントも多く、公式ドキュメントでもその多くのページをOptions APIに割かれています。
むしろ、Composition APIのほうは「これを使おうとしてるあなたにならこれくらいで十分でしょ」くらいのドキュメントしか割かれていません。

### Composition APIとOptionsAPIとの区別はつくようにする必要がある
インターネット上の記事という資産は是非活用していきたいですよね。
ところが、Vue3の登場とともに書き方がComposition APIとOptions APIのものとで混在するようになりました。

これによって、「自分が読んでいる記事はどちらのAPIで書かれているのか」「自分のプロジェクトならどう書けばいいのか」を意識する必要があります。


- `<script setup>` から始まっている　→　Composition API
- setup() メソッドがあり、その中にかかれている → Compotision API
- refとかreactive とかがでてくる → Composition API

setup()メソッドの中でreturn されたメソッドは、 methods 配下に置かれたのと同様に振る舞います。
ref, reactive は data() 配下に置かれたのと概ね同様に振る舞います。computed も同様。
watch, watchEffect はsetup() メソッド内で呼べば（returnしなくても）watch配下に置いたのと同様に振る舞います。
setup()メソッド内で実行したロジックはmounted 相当で呼ばれます。他のライフサイクルは対応するメソッドの中のものがいい感じにマージされます。

ぐらい？ですかね。



## コーディングルールとしてのComposition APIとOptions APIについて
複数人でVueを書くということもあるかもしれません。
その場合、コーディングルールとしてComposition API（またはOptions API）を強制するかという問題に直面することがあります。
これは難しい問題で、難しいです（ぐるぐる目

----

## 結論的なもの
オチをなにも書いてなかったのでモヤっとした記事だったので追記。
あなたがフロントエンドに初めて挑戦するならComposition APIは必要ないでしょう。
また、Vue2は経験が十分にあったとしても、今のコードの複雑性に課題感を抱えていなければ必要ないでしょう。

やってみた系の記事でComposition APIで書かれているものがたくさんでてくるのははしかにかかってると思っていいと思います。

Composition APIを使いこなすには、センスや経験といったものが必要となります。
ReactでHooksの経験があるなら似たような感覚で使えると思います。
今のコードを保守するのは限界だ！ここにComposition APIがハマりそうだぞ？そう思ったときにあなたの強力な武器になってくれるでしょう。
ILE、サービスプログラムのソースメンバー検索方法

## はじめに

コマンドのオブジェクト記述表示`DSPOBJD`を使用して、[OPM ソースメンバーの検索方法](https://qiita.com/tamaday/items/97aee038ae86c96ccee4)をご紹介しました。
しかし、`DSPOBJD`を使用する方法では ILE、サービスプログラムのソースメンバーを検索することができません。

もちろん、ILE、サービスプログラムのソースメンバーを検索する方法も存在します。
この記事ではILE、サービスプログラムのソースメンバー検索方法をご紹介します。


## コマンド

| 対象                 | コマンド                              |
| -------------------- | ------------------------------------- |
| ILE                  | プログラム表示`DSPPGM`               |
| サービスプログラム | サービス・プログラムの表示`DSPSRVPGM` |


## 方法

まずは、`DSPPGM`もしく`DSPSRVPGM`のパラメーターに検索したいソースメンバーのプログラムを指定し、実行します。

![searchSourceMemberile_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/c0b2d8cd-09a5-644e-eb31-c7949bb8c287.png)

そして次に実行をクリックしていくと、「プログラム情報の表示」を確認することができます。

![searchSourceMemberile_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/3c670f9e-60ad-7fe8-d7d5-1f484ebcd76d.png)

さらに「記述の表示」を実行すると…

![searchSourceMemberile_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962887/cde70081-3b4d-c2eb-94d1-851098561a84.png)

ソースメンバーがどこに格納されているか確認することができます。

## おわりに

なぜ OPM と ILE ソースの検索方法が違うかというと、[サービスプログラムを作成できるようになるまで（１）\_サービスプログラムの前提](https://qiita.com/tamaday/items/f99e1c307ff69ee42ee0)でご紹介した、OPM と ILE の作成概念の違いが関係しています。

OPM はソースメンバーから直接プログラムが作成されますが、ILE はソースメンバーから、モジュールを生成し、モジュールからプログラムが作成されます。

ご参考になれば幸いです。最後までお読み頂きありがとうございます。

## 関連した投稿

[OPM ソースメンバーの検索方法](https://qiita.com/tamaday/items/97aee038ae86c96ccee4)
[サービスプログラムを作成できるようになるまで（１）\_サービスプログラムの前提](https://qiita.com/tamaday/items/f99e1c307ff69ee42ee0)
GPT-3を使ったAIの「忘年会参加お断り文」が出来上がるCatchyを試してみた

先日、OpenAIが発表したGPT−３を使った**ChatGPT**が話題になりました。
続いて話題になってるのが、「忘年会参加お断り文」を作ってくれるAIの**Catchy**を試してみました。

## 登録
https://ai-copywriter.jp/

![スクリーンショット 2022-12-17 16.57.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/60200be4-4bd8-d3df-fc9c-ac7e27e770a4.png)

## チュートリアル
会員登録のチュートリアルの中で、お試しで文章を入力を求められたので、
>記事を書くのは難しい

と入れて出てき文章が下記です。

>記事を書くのは難しい。文法や構文に気を配りながら、説得力のある文章を書くことが求められます。さらに、複雑な内容であっても、その内容を深く理解し、正確で興味深い記事を書く必要があります。また、事実や数字が正しいか、最新の情報であるか、十分なリサーチが必要です。さらに、読者の興味を引くような内容にするために、適切な用語や語彙を使い、ターゲットとなる特定の読者に合わせて記事を作成する必要があります。最後に、ライターは自己批判を行い、自分の作品の改善点を認識し、積極的にフィードバックを求めて作品の質を高めていくことが必要です。このように、記事を作成するプロセスは厳しく困難なものですが、適切なスキルセットと適性があれば、記事作成の技術を完成させることは決して難しいことではないのです。

ダッシュボードはこんな感じです。
![スクリーンショット 2022-12-17 17.07.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/0b63ecdc-fe50-c285-ddbd-424f4a949cb0.png)

生成ツールを開くと
![スクリーンショット 2022-12-17 17.08.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/520fdf39-3dc1-311a-f427-c2710bfee22a.png)

## 忘年会の参加を断る
忘年会の参加を断るを選択してみました。

>もしかしたら仕事に行かないと駄目かもしれない

と入力し作成するボタンを押下

>残念ながら、会社の忘年会には出席できません。私は仕事をすることが求められているため、仕事を確実にこなすことを優先しなければなりません。特に、この職務への献身的な姿勢を示すために努力しています。チームのみんなと一緒に今年の成功を祝うことができないと思うと、悲しい気持ちになります。しかし、みんなが帰ってきたら、その話を聞くのが楽しみです。きっと楽しい夜になると思います。

なんか、大袈裟に硬すぎて、嫌がられそうじゃありませんか？？文章の雰囲気をカジュアルに変更してみました。

>会社の忘年会に出られなくて、とても残念です。残念ながらその日は出勤しなければならないのですが、私が取り組んでいるプロジェクトの締め切りがその日なので、欠席するわけにはいかないのです。この数ヶ月間、私が集中し、優先してきたプロジェクトなので、本当に重要であり、もうすぐ全てがまとまるのを見るのが楽しみです。もちろん、お祭りや楽しみを逃してしまうのは本当に悲しいですが、それでもきっとみんなは素晴らしい時間を過ごすことでしょう。ご理解いただき、ありがとうございます。

まーなんとなく良さそうです。

## ユーザーの興味を引くメール件名
ユーザーの興味を引くメール件名をやってみました。

スカウトメールを入れてみます。

>はじめまして。
合同会の採用担当をしております森川と申します。
森川様のご経歴を拝見し、ぜひ一度お話をさせて頂きたいと思いご連絡させていただきました。
理由としては、B社でのエンジニアのご経験から、弊社が現在募集しているエンジニアのスタッフとしてご活躍いただける人財だと高く評価しているからです！
また、今回エンジニアの職種をご希望されているということでA様のご期待に添える環境がご提供できると思っております。
今回の募集は広く公開しておらず、弊社が選考にお呼びしたい方だけにご連絡しておりますのでA様にご興味をお持ちいただけると大変嬉しいです！
他にもいろいろとお伝えしたいのですが、ぜひ直接お話しさせて頂き、お互いを知り合うことができ
スケジュール調整はもちろんご面談の方法もオンラインやお電話などで柔軟に対応致します。 
それでは、A様からのお返事を心よりお待ちしております！

- Aさん、あなたに採用のチャンス！？
- 技術スタッフへのお誘い!
- エンジニアとして次のステップへ
- Aさんに特別採用のチャンス！？
- 私たちのエンジニアチームの一員になりませんか？
- ..Aさん、エキサイティングなチャンスがあなたを待っています。
- 当社のエンジニアチームであなたのキャリアを再創造してください。
- エンジニアとして活躍する。
- やりがいのある技術者集団の一員になろう
- エンジニアとしてのキャリアを輝かせる

10個のメール件名をレコメンドしてくれました。
- エンジニアとして次のステップへ
- ..Aさん、エキサイティングなチャンスがあなたを待っています。
- 当社のエンジニアチームであなたのキャリアを再創造してください。
- やりがいのある技術者集団の一員になろう
この辺りは使えそうかも知れませんね。

# まとめ
裏側では、OpenAI GPT-3 APIを叩いてるいるだけかもしれませんが、フォームから入力させる事により、細かい指示の補足が出来るので、生成文章がより適切なものに導くことが出来るんだと思います。
但し、生成文章は、すごい感じもありますが、まだまだ人間の方がクリエイティブ力はありそうにも感じます。
こういうメール件名作る時には、ネットからどんなメール件名が良いかと検索したりする事を考えたら、10個のレコメンドは、考えていくための材料としては良さそうな気がしました。
逆に考えれば、このレベルのメール件名を付けてしまう仕事をしていると、スグに仕事がなくなる事を意味するんだと思い、心が引き締まります。
ひき続き記事を書いていきますので、フォロー、イイねお願いします！
【備忘録】git コンフリクト解消

branchをdevelopにプルリクエストを送った時にコンフリクトが起きた時の解消方法

1. git branch 現在のブランチを確認（master以外)
2. git checkout ブランチ名
3. git merge develop
4. git status
5. both modificationになっているファイルをVS Codeの場合はマージエディタで手動でマージ
6. git add .
7. git commit -m "コンフリクトの解消"
8. git push
Tensorflowで会話AIを作った時に色々と物理的問題が発生した話

# はじめに
どうもこんにちはこんばんは、S高2期通学生のKen_Cirです、今回は僕がTensorflowで会話AIを作るときに衝突した物理的問題(特にGPU)の話をします、もし今後機械学習する方の参考になれば幸いです。

# そもそもなんで会話AI？
これにはいろいろと理由があります、第一にただ話し相手が欲しかったからなんですけどね。
ただ会話AIってのは非常に奥深い気がします、学習パターンとかモデルとかデータセットを変えれば根本的に変わる気がします。
今回僕が会話AIを作るのに参考にした記事は以下に載せておきますので、興味のある方はぜひぜひ！
- [注意を払ったニューラル機械翻訳](https://www.tensorflow.org/text/tutorials/nmt_with_attention?hl=ja)
- [Kerasで実装するSeq2Seq](https://qiita.com/gacky01/items/26cd642731e3eddde60d)

# 今回学習に使用したPCやクラウド
### 1. ゲーミングWindows
まず僕は自分が使っていたゲーミングPC(BTO)を使用しました、比較的少ないデータならなんとか動いてくれたのですが、
かなり大量にデータを増やしたらVRAM(GPUメモリ)不足で動いてくれませんでした。
スペックは以下の通り
- CPU:i7-12700
- GPU:NVIDIA GeForce RTX 3070 Ti
- RAM:16GB

### メリット
- 既にゲーミングPCがある人は新たにPCを買わなくていい

### デメリット
- 機械学習中はゲームできない(GPUを使用しないならいけるかも)
- GPUにもよるが、かなり大量のデータ学習には向いていない

話がずれますが、state diffusionを動かしたときも8GBのVRAMをほぼ使い切るほど重かった記憶。
これじゃあ会話AIといえるAIが作れないじゃないか！ということで次に使用したのはGoogle Colaboratoryです。

### 2. Google Colaboratory
天下のGoogle社が提供している、Web上で機械学習ができるという素晴らしいサービス、
ゲーミングPCを持っていないという人にとっても気軽に機械学習を試せるので使いやすいです。
課金すればそれなりの大容量のデータセットでも動くので一時期は本当に助かった記憶。
僕はColab Proを1ヵ月ほど使っていました。

[料金プラン](https://colab.research.google.com/signup/pricing?hl=ja)
![スクリーンショット 2022-12-17 174107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2349828/5729d0d8-f0d7-2ae5-674b-643eb3cef6b5.png)


### メリット
- 制約はあるが無料で使える
- 有料だとかなり高性能なGPU(A100など)が割り当てられる
- 手軽に試せる

### デメリット
- 無料版だと12時間で初期化される(データが飛ぶ)
- 課金しても動かせる時間は決まっているのでそこア編を注意して使わなければならない

正直Google Colabでも十分だと思います、が長期的や、AI系のサービスを提供する場合はGPUサーバーが必要になってきますよね。

### 3. GPUサーバー(Ubuntu)
GPUサーバーって言っていますが実態はUbuntuにGPU積んだサーバー機です。
ゲーミングPCを犠牲にできない、クラウドサービスは長期的に見ると金銭的に厳しい、という結果今まで貯めたお金を犠牲にGPUサーバーを構築しました。
スペックは以下の通りです。
- CPU:i5-12400F
- GPU:NVIDIA RTX A4000
- RAM:32GB

RTX A4000の相場は[価格com](https://kakaku.com/item/K0001367072/)によると13万円～18万ほど、ただ僕はメルカリで9万ほどの中古品を手に入れることができました。
導入した結果

### めっちゃ爆速

ゲーミングPCとは比にならないほど早かったです(当たり前)、Google Colabより性能は劣りますが、個人でやる分にはこれくらいで十分な気はします、ただもう少しいいGPU欲しかったな。

### メリット
- 一度導入すれば時間とか気にせず好きなだけ回せる
- サービス提供も可能
- サーバー機なので機械学習以外にも使用可能

### デメリット
- GPUは高い
- VRAMやcudaコアは増設できないのでGPUは慎重に決める必要がある
- 電気代などの別問題も発生する

本当にお金に余裕のある人にはおすすめします、ただ維持的な問題や電気代など色々課題が多いのが難点。
ただ僕はサーバーに飢えていたので、機械学習以外にも転用できるのを考えると、まだマシなのかな...
もしGPUサーバー自作する人が居たら、GPUは許す限り高性能のやつ買っておきましょう。

# AIを作ってみて思ったこと
高性能のAIを作るにはその分高性能のGPUも必要なのか...ってのを実感させられました。
OpenAIとかMidjourneyとかはどんなGPU使っているのかな、ってのも結構気になっていたり。
ただ最近はGoogle Colabとかで手軽に試せるので比較的ハードルは下がったのではないでしょうか。
ぜひもっとAIに興味を持ってくれる人が増えてくれるといいですね。
今度は音声合成AIでも作ってみようかな。

# 終わりに
なんかもう少し技術方面の記事書きたいなーと思ったんですが、自分の機械学習に対する理解が全然ないのでほぼ他記事便りにしながら会話AIは作っていました（笑）
ただその際物理的問題(ほぼGPU)に当たったので、もし今後機械学習する方の参考になれば幸いです。
最後まで見てくださりありがとうございました！
Rails　gemのアンインストールをする方法

# はじめに
作成したアプリケーションをAWSでデプロイしようと進めていましたが、都合によりrenderでデプロイする方向に切り替えました。
無事にデプロイできたものの、ブラウザで確認すると、**保存はできているが画像の表示が上手くいっていない**状態になりました。（窓のアイコン？が出てきてしまう状態）
AWSにてバケットの作成を行なっていたので、そこら辺に問題ありかなと考え問題解決までの道のりを書き残したいと思います。


# エラーの内容
保存した画像が表示されるページへ遷移したときに、ターミナルにて以下のエラーが出ました。

```ruby:ターミナル
ActiveStorage::FileNotFoundError (ActiveStorage::FileNotFoundError):
```
原因は自分の中でなんとなくわかっていて、冒頭にも書きましたが、AWSでのデプロイ作業の途中でrenderでのデプロイに切り替えたことかなと考えました。
AWSでバケットの作成をするにあたり、画像をS3に保存するためにaws-sdk-s3をインストールしていました。
このgemをアンインストールすると解決できると思い、実行しました。

# gemのアンインストールの方法
```ruby:ターミナル
bundle exec gem uninstall aws-sdk-s3
# bundle exec gem uninstall <gem名> コマンドを実行
```

```:ターミナル
Successfully uninstalled aws-sdk-s3-1.117.1
# aws-sdk-s3-1.117.1 が正常にアンインストールされましたという意味です
```

そして、vscodeのGemfileを開き以下を削除します。

```:vscode
gem "aws-sdk-s3", require: false
```
```:ターミナル
bundle install
```

rails sをしてブラウザで確認すると、見事に画像が表示されるようになりました。
解決して良かったです。
【Rails API】手動でコントローラを追加する方法【備忘録】

1. api/v1/examples_controller.rb を作成
2. config/routes.rbにresourcesを追加（ルーティングを追加する）
3. index アクションなどを作成
4. http://localhost:3000/api/v1/examples?parameter=1

```bash
##チェンジディレクトリ
cd controller/api/v1

##ファイル作成
touch example_controller.rb
```

自動で作成する場合(scssファイルとhelperファイルが不要な場合はオプションをつける)
```bash
rails g controller api/v1/examples index create --no-assets --no-helper
```
Error occured: Invalid ttl in dnsrecord【Freenom】

TTLに299以下を入れるとエラーになる。300を入れよう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/664781c1-d9c8-fdf3-fa9b-65240ee0d6cb.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/4cd11853-02b4-9243-933e-9c3d378a6f65.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/7ce81df4-7cad-446c-3100-74237ea2fe49.png)



# 反映するまで監視

8分くらいで反映されます

```bash
while true; do date; nslookup example.tk; sleep 10; done
```
ES2022で追加された便利そうな機能

## 配列の最後を取得できる`at()`

引数にマイナス値を指定すれば、配列の末尾から参照してくれる

```js
const array = [1,2,3]
console.log(array.at(-1)) // 3
```
こう書かなくてよくなった

```js
console.log(array.at(array.length - 1)) // 3
```

https://github.com/tc39/proposal-relative-indexing-method
[python] Djangoで今日のカレンダーを表示する


# 環境
Django 3.1.13
Python 3.9.13

# Code
```terminal:Tree
├─core
│  ...省略
├─events (カレンダー表示目的で今回使用する)
│  ├─migrations
│  └─templates
└─myapp
│  ├─urls.py
│  ├─settings.py
│  ...省略
└─manage.py
```

```python:myapp.urls.py
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('core.urls')),

    # このurl
    path('events/', include('events.urls'))
]
```

```python:events.urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('<int:year>/<str:month>', views.home, name='home'),
]
```
`/events/2020/June` → year=2020, month=June
のような形でパラメータを受け取る

   

```python:events.views.py
from django.shortcuts import render
import calendar
from calendar import HTMLCalendar
from datetime import datetime

def home(requests, year=datetime.now().year, month=datetime.now().strftime('%B')):
    # パラメータがない場合、今日の日付になるようにした。

    month_number = list(calendar.month_name).index(month)
    month_number = int(month_number)

    # カレンダー
    cal = HTMLCalendar().formatmonth(year, month_number)

    # 今日の日付を得る
    now = datetime.now()
    current_year = now.year
    current_month = now.month
    time = now.strftime('%I:%M %p')

    return render(requests, 'home.html',
                  {"year": year,
                   "month": month,
                   "month_number": month_number,
                   "cal": cal,
                   "current_year": current_year,
                   "current_month": current_month,
                   "time": time})
```


```html:events.home.html
<div>
    <center>
        <br>
        {{cal |safe}}

        <br>
        Now:
        {{current_year}} / {{current_month}}
        {{time}}

    </center>
</div>
```



# カレンダー表示
## 日付指定なし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/ee8260e5-5e6f-aa65-2d02-8d9e06ba1781.png)

## 日付を指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/e7c885ca-cb2d-09e8-bab4-f857d900c84b.png)


# おわりに
`nodejs`, `flask`のようなマイクロフレームワークを触って`Django`に触れると、ルールが多くて不便だと思っていたが、意外と便利さを感じる。



https://www.youtube.com/watch?v=NVeV7Y3BkF4&list=PLCC34OHNcOtqW9BJmgQPPzUpJ8hl49AGy&index=3
運営者ギルドへの誘い

何かをつくるのに一番必要なのは、動機づけだ。効果的なのはコンテストに応募してしまうこと。締め切りが作られることで、なんとか完成させる気持ちが出てくる。

または、なにかしらのコミュニティに所属するのもおすすめ。そういう理由で、わたしは運営者ギルドに入った。


https://adminguild.notion.site/adminguild/05239b17becd4657a1506d7e2ea7016c

運営者ギルドは個人サービスを運営している人たちによるギルド。数百人規模のコミュニティだ。Slackのコミュニティでは、各自がチャンネルをもっていて、いろいろ呟いている。

チャンネルが多すぎて全部は追えないが、みんな何かしらのサービスを作っているので、やる気が出てくる。

slackチャンネルのひとつにbugdashというのがあって、公開したサービスのフィードバックをもらえる。私はまだ使ってないが、来月は出す。

入会費もかからないし、強制的なイベントもない。ゆるいつながりのまま、個人開発の意欲を維持する。ちょうど良い場所だとおもう。
Webアプリケーションの脆弱性クイズアプリを作ってみました

# はじめに
こんにちは、株式会社シーエー・アドバンス技術統括本部の宮里です。

普段は業務でWebアプリケーションやAndroid,iOSアプリなどの脆弱性診断を行っています。
今回はWebアプリケーションの脆弱性クイズアプリを簡単に作ってみましたので紹介します。

## 脆弱性とは
脆弱性とは、OSやソフトウェア、プログラムの不具合や設計上のミスが原因となって発生する**悪用できるバグ**を指します。

詳しい解説はこちらが参考になると思うので、興味がある方はぜひ見てみてください。
https://www.soumu.go.jp/main_sosiki/joho_tsusin/security/basic/risk/11.html

### 作った経緯
個人的に趣味でUnityを触る機会があったので、アドベントカレンダーをきっかけに普段の業務の紹介に繋がるような簡単なアプリを作ってみようと思ったのがきっかけでした。

スクリプトはC#で書いています。

### クイズについて
今回は、以下の脆弱性についてのクイズを用意しました。

1. クロスサイトスクリプティング（XSS）
2. クロスサイト・リクエストフォージェリ（CSRF）
3. SQLインジェクション
4. メールヘッダ・インジェクション
5. アクセス制御の不備

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/a21693c7-5794-acfe-b986-49ff1fa37da1.png" width=50%>

「アクセス制御の不備」に関しては、パッとイメージつきにくいかもしれませんが、ぜひアプリをインストールして確認してみてください！！

誰が、どういう操作を行う事ができるのが適切か を考えるとヒントになると思います！

また、今回はiOSには対応しておらずAndroidアプリのみになりインストールの手順は省略します。

#### アプリの作成について
Unityを利用してアプリを作成する際にスクリプトをいくつか書きました。
初めての経験でUnityならではの部分もあって楽しく作成することが出来ました。

Unity側で用意したオブジェクトをスクリプト上で取得したり、変更したりする場合、スクリプト上で変数を定義した後にUI上からドラッグ＆ドロップで当てはめる必要があったり、

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/7851739b-3661-2a5d-33bc-1f7d660ebb4b.png" width=50%>

（答えが載っちゃってますかね？気のせいですよ）

正解音、不正解音は著作権フリーの素材から探したりして普段と違う作業をしている感じが新鮮でした。
今回はこちらから利用させていただきました。
https://soundeffect-lab.info/

画面の崩壊もしっかり経験しました（端末によって線がずれてしまう）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529348/11da0d19-701a-d7ee-d38f-6ffa184cf895.png" width=50%>

#### ゲームとしての作りこみ
今回、もっと出来たなと思う所は以下の点でした。

1. 4択の回答が毎回同じ並びなのでランダムに出来たら良かった
2. 画面が味気ない
3. 結果を表示する時、点数を最後に出すなどのアニメーションを作れたら良かった

世の中のゲームを作る人達は気を遣ってゲームを作っているんだなと感じる事が出来て面白かったです!

#### 最後に
apkはこちらにあります、良かったら遊んでみてください～
https://github.com/miyazato1014/quiz/releases/tag/apk
【HTML/CSS】Chromeのdevelopperツールでよく使う機能

HTMLやCSSを微調整するときに便利なデベロッパーツールの使い方。
初心者向けです。他にも便利な使い方があったら教えてください！
※あとでGIFを入れる

# HTML
## 要素を入れ替える
ドラッグ＆ドロップでできます。

## 要素を複製する
コピペ（Ctrl＋C → Ctrl＋V）でできます。
選択した要素の最後の子要素として追加されます。

## 文字列を編集する
ダブルクリックで編集できます。文字列の編集なので、HTMLタグを入れてもテキストで表示されるだけです。

## 要素を編集する
F2で編集できます。HTMLタグも反映します。
Ctrl＋Enterで編集完了（確定）します。

## hover
疑似的にhoverしたい要素の左の「・・・」をクリック。
forcus state > :hover　を選択します。

※stylesの「:hov」からもできます。

# CSS
右側のStyles・Computedを使いこなす。

## 10pxずつ上下させる
Stylesの該当箇所をクリックして、Shift＋↑↓。

## 0.1pxずつ上下させる
Stylesの該当箇所をクリックして、Alt＋↑↓。

## 100pxずつ上下させる
Stylesの該当箇所をクリックして、Shift＋Alt＋↑↓。

## flexは選択で
display: flex; は右側にあるマークをクリックして視覚的に配置方法を選択することができます。

## どこのCSSが効いているのか確認する
ComputedのFilterで検索。
例えば、font-sizeで検索したときに該当箇所の「→」を押すと、Stylesタブで指定されている箇所まで移動します。


JavaScriptを使う時のEvent Listenersなんかもいろいろできるので書き足していきたい所存です。