OmniAICreator/Qiita-1.07M huggingface dataset:
How to install Nextron(Next js + electron)?

## そもそもNextronとは何なのか

Nextronとはelectron+NextJSの環境を今までより簡単に構築できるようにつくられた(らしい)ツールです。とはいえ私はいきなりこれでやったので今までのやり方をしらないんですけども結構開発がしやすいです。

## プロジェクト作成方法

まずは以下のコマンドを入力

```
npx create-nextron-app <ProjectName>
```

割と軽めなので回線が良ければすぐ終わります。

そして
```
npm run build 
```
と入力してビルドします。これをしないとエラーになるのでお気を付けて。通常のelectronだとpackage.jsonとかmain.jsを作成・編集しないとうまく起動しませんが、Nextronは勝手にやってくれるので楽ですね。

んじゃあ

```
npm run dev
```
と入力すれば実行できます。

ちなみに起動時は開発者ツールが自動で立ち上がります。メインページはrender/pages/home.jsxとなります。まずはそのファイルを編集して挙動を確かめてみましょう。

それでは。
GitHub ActionでJavaScriptのフォーマット漏れをチェックする


# 設定

## 1. prettierの設定
prettierの導入をします。様々なサイトで案内されているのでそちらを参照して下さい。
例）https://ics.media/entry/17030/
以下のようにpackage.jsonに記述がされると思います。
```json:package.json
{
  "scripts": {
    "format": "prettier --write src"
  },
  "devDependencies": {
    "prettier": "^2.7.1"
  }
}
```

## 2. GitHub Actionの設定
Node.jsのversionが14の例です。
PullRequestが生成されたら、こちらのActionが実行されます。

```bash: .github/workflows/pre-merge.yml
name: Pre Merge

on:
  pull_request:
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  test:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        node-version: [14.x]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v2
        with:
          node-version: ${{ matrix.node-version }}

      - name: Install npm
        run: npm ci

      - name: Format code
        run: npm run format

      # format後にgit addして差分があるかgit diffでチェック
      - name: Check diff exists 
        run: |
          git add -N .
          git diff
          line=`git diff | wc -l`
          if [ $line -gt 0 ]; then
            echo "You need to format before commit"
            git diff
            exit -1
          fi
```

# テスト
セミコロン忘れのPRを作成します。そうすると自動的にGitHub Actionが実行され、フォーマット漏れを検知しています。
![Screen Shot 2023-02-01 at 14.51.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81962/8a266b2d-0496-e6ca-ad8e-67ba2e961022.png)

その結果、PRはCheck Failedとなります。
![Screen Shot 2023-02-01 at 14.51.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81962/613c8922-d089-d600-628d-b0b513bbec9b.png)

# 最後に
タイトルではJavaScriptと書いていますが、prettierが対応している言語でしたら、もちろんチェック可能です。

以上
【GAS】ニコニコ動画のコンテンツツリーを取得する方法【ニコメア】

# はじめに

前回はニコニコ動画の広告者を取得する方法を紹介しました。

https://qiita.com/vram/items/8517cb0e8537bf4a24d2

今回は動画内で使用している素材リスト、コンテンツツリーを取得する方法を説明します。

# コンテンツツリーの取得
コンテンツツリーを取得する処理はシートのクリア、動画IDの取得、スレッドIDの取得、コンテンツツリーの取得の4種類で構成しています。
スレッドは使っていませんが動画情報表示のため呼び出しています。

```getContents.js
function getContents(){
  sheetInfoClear()
  sheetContentsClear();
  let id = getId();
  let threadId= HttpInfo(id);
  HttpContents(id);
}
```
# シートのクリア
他の処理と同じですセルの範囲が異なります。

```sheetContentsClear.js
function sheetContentsClear(){
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('コンテンツ');
  let y=5;
  const lastRow = sheet.getLastRow();
  sheet.getRange(y, 2, lastRow, 4).clearContent();  
  sheet.getRange('B2').clearContent();
}
```

# コンテンツツリーの取得
コンテンツツリーは下記の方法で取得します。特殊な記述としてはサムネイルに **('=IMAGE("**  サムネイルURL　**")** としているところです。
これはExcel2022やGoogleスプレッドシートで指定したUrlの画像を表示する命令です。

コンテンツツリーは20以上登録している動画もありますが処理の都合上、20を上限としています。

```HttpContents.js
// 指定したIDからコンテンツを取得し表示 
function HttpContents(id){
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('コンテンツ');
  url = "https://public-api.commons.nicovideo.jp/v1/tree/" + id
  url = url + "/relatives?with_meta=1&_offset=0"
  url = url + "&_limit=20"
  const docText = UrlFetchApp.fetch(url).getContentText();
  let json = JSON.parse(docText);
  let data = json["data"];
  let parents = data["parents"];
  let total = parents["total"];
  if (total>20){total=20}
  contents = parents["contents"];
  let k = 0;
  let s = "";
  for(let j=0;j<total-1;j++){
    let content = contents[j];
    if (content === undefined) {
      break;
    } 
    let thumbnailURL = content["thumbnailURL"];
    sheet.getRange(k+5, 2).setValue('=IMAGE("' + thumbnailURL+'")');
    sheet.getRange(k+5, 3).setValue(content["globalId"]);  
    sheet.getRange(k+5, 4).setValue(content["title"]); 
    sheet.getRange(k+5, 5).setValue(content["description"]);  
    if (j > 0){
      s = s + " ";
    }
    s = s + content["globalId"];
    k++;
  }
  sheet.getRange(2, 2).setValue(s);  
}
```

# 最後に
いかがでしょうか？

意外と簡単にコンテンツツリーが取得出来ることがわかりました。

上記方法で作成したニコメアのDLはこちら

[ニコメア](https://commons.nicovideo.jp/material/nc289171)
[Flutter] 今のコードをちょっとよくする（constants編 その1）


こんにちわ。いせきです。

私は今大学4年生なのでもうすぐ卒業です。寂しいです。
来年度は、大学院＋社会人をやっていくので修羅の道になりますが、頑張っていこうと思います。



さて、<b>「今のコードをちょっとよくする」</b>シリーズもいい感じに集まってきましたね！！（２個ぐらいしかないと思っていました。）


今回は、定数を定義していこうと思います。

そうすることで
<b>
・保守性が上がる。
・重複を減らしコードの可読性が高められる。
・コンパイラが定数値を最適化し、パフォーマンスが向上する
・定数を強く型付けすることができ、コンパイル時のエラーを発見しやすくなる
・メンテナンスが容易になる
</b>

どうでしょうか？これだけでもいいコードになりそうですね。

# 使い方

以下の値は、定数なので、static(静的)、constにて定義してあげる。
詳しくは以下のコードを参考にしてください。

今回は、色を定数化していこうと思います（別の種類もあります。別の記事にて。。）

```dart
import 'package:flutter/material.dart';

class ColorConstants {
  static Color appBarColor = const Color(0xFF4A67AD);
  static Color backgroundColor = const Color(0xFFF2F2F7);
  static Color settingsListBackground = const Color(0xFFF2F2F7);
  static Color settingsSectionBackground = Colors.white;
  static Color yellow = Colors.yellow;
  static Color lightBlue = Colors.lightBlue;
  static Color blue = Colors.blue;
  static Color grey = Colors.grey;
  static Color black = Colors.black;
  static Color white = Colors.white;
  static Color red = Colors.red;
}
```

作成した定数を他のファイルから使用したいときには以下のようにして呼び出す必要があります。

```dart
import 'package:flutter/material.dart';
import 'package:sample_app/constants/color_constants.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Qiita Flutter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key}) : super(key: key);

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int counter = 0;

  void _incrementCounter() {
    setState(() {
      counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Qiita Flutter App')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
              style: TextStyle(
                //繰り返し使える
                color: ColorConstants.appBarColor,
              ),
            ),
            Text(
              '$counter',
              style: TextStyle(
                //繰り返し使える
                color: ColorConstants.appBarColor,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}



```


# 最後に
ChatGPT便利じゃないですか？？わからなくなったら聞いてみることでアドバイスがもらえる。改めてですが革新だなと思っていました。（最初は食わず嫌いで使っていませんでした。）
記事で回答に困ったら使えるので記事要らなくね？と思うこともありますが、自分自身のアウトプットのために頑張ります〜〜〜！！！！
AndroidのWebViewで、画面回転した後にフォーカスを当ててもソフトウェアキーボードが表示されない不具合に対する回避策

# 要件
Androidで以下のような要件がありました。

- WebView画面
- 縦画面でコメントが入力できる
- WebChromeClientから受け取ったView(動画)を全画面(横画面)で表示する

# 不具合
この時特定の端末で
「画面回転をした後に、WebView内の入力欄にフォーカスを当てても、ソフトウェアキーボードが表示されない」
という症状がありました。

# 再現手順
- 該当の画面に遷移する
- WebView内の動画を最大化して、横画面で表示する
- 縦画面に戻す
- WebView内のテキスト入力欄にフォーカスしても、ソフトウェアキーボードが表示されない

# 修正方法
回避策として、以下の実装を行いました。
```kotlin WebViewActivity.kt
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    webView.clearFocus()
    webView.requestFocus(View.FOCUS_DOWN)
}
```
一度WebView内のフォーカスをクリアしてから、再度WebViewにフォーカスを当てます。
そうすると、テキスト入力欄を選択した(フォーカスが当たった)ときに、ソフトウェアキーボードが表示されるようになります。

# 終わりに
あまりこういった要件のケースは無いと思うのですが、意外と解決に時間がかかってしまったので、
こちらを共有したいと思います。
【Teams】メッセージ入力時のショートカット 20 選！

# はじめに
どうも、ATLのヴィリアスです。

今回は、私がよく使う **Teams でメッセージを入力するときに使えるショートカット**を
超基本的なものから、あまり知られていないものまで、簡単にまとめてみました。

# ショートカット一覧

| 操作 | ショートカット | 説明 |
|:---|:-:|:--|
| コピー  | ```Ctrl``` + ```C```  | 選択した文字列をコピーします。 (**C**opy)  |
| ペースト  | ```Ctrl``` + ```V```  | コピーした文字列をペースト (貼り付け) します。  |
| 書式設定なしでペースト  | ```Ctrl``` + ```Shift``` + ```V```  | Word や Excel の文字列をコピーして<br>Teams に貼り付けようとすると、そのままの書式設定で貼り付けられることがあります。<br><br>このショートカットを使うことで、書式設定を無効にして文字列を貼り付けることができます。  |
| 切り取り  | ```Ctrl``` + ```X```  | 選択した文字列を削除しつつ、コピーします。  |
| 元に戻す  | ```Ctrl``` + ```Z```  | 直前の操作を取り消します。  |
| やり直し  | ```Ctrl``` + ```Y```  | 直前の「元に戻す」を取り消します。  |
| 太字  | ```Ctrl``` + ```B```  | 選択した文字列を**太字**にします。 (**B**old)  |
| 斜体  | ```Ctrl``` + ```I```  | 選択した文字列を***斜体***にします。 (**I**talic)  |
| 下線  | ```Ctrl``` + ```U```  | 選択した文字列に<ins>下線</ins>を引きます。 (**U**nderline)  |
| ハイパーリンク  | ```Ctrl``` + ```K```  | 選択した文字列を[ハイパーリンク](#)にします。 (hyperlin**K**)  |
| 取り消し線  | ```~(文字列)~```  | 文字列に ~~横線~~ 取り消し線を引きます。<br><br>任意の文字列を "**~**" で囲みます。 |
| メッセージを "重要" としてマーク  | ```Ctrl``` + ```Shift``` + ```I```  | 入力中のメッセージを "**重要**" としてマークします。 (**I**mportant) |
| 段落を変える (改行) | ```Enter```  | (書式設定オプションを開いているとき)<br>段落を変えます。  |
| 文章の改行  | ```Shift``` + ```Enter```  | (書式設定オプションを開いているとき)<br>文章を改行します。<br><br>"箇条書き" や "ナンバリング" (後述) に有効です。  |
| メッセージ送信  | ```Ctrl``` + ```Enter```  | 入力中のメッセージを送信します。  |
| 引用  | 文頭で```>``` + ```半角スペース```   | 引用ボックスを追加します。  |
| 箇条書き  | 文頭で```*``` + ```半角スペース```  | 箇条書きを開始します。  |
| ナンバリング  | 文頭で```1.``` + ```半角スペース```  | ナンバリングを開始します。  |
| [新規作成] ボックスに移動  | ```Alt``` + ```Shift``` + ```C```  | メッセージ入力欄に移動します。  |
| [新規作成] ボックスを展開  | ```Ctrl``` + ```Shift``` + ```X```  | メッセージ入力欄の書式設定オプションを開きます。 (e**X**pand)  |

あとは ```Ctrl``` + ```Alt``` + ```数字``` のショートカットもありますが使わない…
(```Ctrl``` + ```Alt``` + ```5``` で等幅フォント)

# おわりに


ここで挙げたもの以外にも「**こんなショートカットあるよ！**」というものがありましたら
情報共有いただけるとうれしいです！

( 個人的には [インデントを増やす・減らす] とか [書式設定クリア] とかができたらうれしい )

それでは、良い Teams ライフを～

# 参考にしたもの

https://support.microsoft.com/ja-jp/office/microsoft-teams-%E3%81%A7%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88-%E3%82%AD%E3%83%BC-2e8e2a70-e8d8-4a19-949b-4c36dd5292d2
MVVM+CoroutineFlowのUnitテストを書く（準備編）

## はじめに
ついにUnitテストと真面目に向き合う時がやってきたので、採択技術や書き方をメモしておく。

## 採択したもの
- JUnit4
- Mockk
- Truth(Googleが出しているアサーションライブラリ)

↓kts化してない人は読み替えてください
```build.gradle.kts(app)
    // test
    testImplementation("junit:junit:4.13.2")
    testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.8.2")
    androidTestImplementation("androidx.test.ext:junit:1.1.5")
    androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
    testImplementation("io.mockk:mockk:1.12.5")
    testImplementation("com.google.truth:truth:1.1.3")
    testImplementation("androidx.arch.core:core-testing:2.1.0")
    testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1")
```

## なぜそうしたのか
- Mockk : Coroutineをサポートしているライブラリだから。
    - coEvery{} と書くとCoroutineによる処理の実行がモックできる。
- Truth : 値の比較をするための鉄板ライブラリ。
- JUnit4 : 一旦慣れているものを使う方向で。追々JUnit5に移行したい。

## 参考にした本、サイト
Android ユニットテスト ヒッチハイク・ガイド | 糖衣構文
https://syntaxsugar.booth.pm/items/4186246

【Android/Kotlin】JUnit4 によるユニットテストを試してみた
https://zenn.dev/kotaro666/articles/android-unit-test-sample

ahmedeltaher/MVVM-Kotlin-Android-Architecture
https://github.com/ahmedeltaher/MVVM-Kotlin-Android-Architecture
Ubuntu22.04のUbuntu-drivers autoinstallでubuntu-drivers "UnboundLocalError: local variable 'version' referenced before assignment" when installing nvidia driversエラー

新規導入したPCにUbuntu22.04を入れ、nvidia-smiを使用するためにUbuntu-driversでドライバをダウンロードしようとしたところ次のようなエラーが発生した。

```
$ ubuntu-drivers devices
~~ここに導入可能なドライバ一覧が表示
$ ubuntu-drivers autoinstall
Traceback (most recent call last):
  File "/usr/bin/ubuntu-drivers", line 513, in <module>
    greet()
  File "/usr/lib/python3/dist-packages/click/core.py", line 1128, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1053, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1659, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/lib/python3/dist-packages/click/core.py", line 1395, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/decorators.py", line 84, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 754, in invoke
    return __callback(*args, **kwargs)
  File "/usr/bin/ubuntu-drivers", line 413, in install
    command_install(config)
  File "/usr/bin/ubuntu-drivers", line 187, in command_install
    UbuntuDrivers.detect.nvidia_desktop_pre_installation_hook(to_install)
  File "/usr/lib/python3/dist-packages/UbuntuDrivers/detect.py", line 839, in nvidia_desktop_pre_installation_hook
    with_nvidia_kms = version >= 470
UnboundLocalError: local variable 'version' referenced before assignment
```

https://askubuntu.com/questions/1436601/ubuntu-drivers-unboundlocalerror-local-variable-version-referenced-before-as

こちらによるとpythonで書かれたインストーラーの"-"を区切る場所がおかしいためにこのエラーが出るらしい

# 解決法１

指定されたドライバーをaptでインストールする

```
sudo apt install nvidia-driver-<~~~>
```

# 解決法２

インストーラーを修正する

```
sudo vim /usr/lib/python3/dist-packages/UbuntuDrivers/detect.py
```
で該当ファイルを開き
`version = int(package_name.split('-')[-1])`
この部分を
`version = int(package_name.split('-')[2])`
に修正する。

すると
```
ubuntu-driver autoinstall
```
が実行できるようになる
Python3: A4横 の PDF をマージして A3 にする

A4横 のファイルを上下に並べて A3 にします。

## プログラム

```py:pdf_merge_landscape.py
#! /usr/bin/python
#
#	pdf_merge_landscape.py
#
#					   Feb/01/2023
#
import  sys
import  PyPDF2
from PyPDF2 import Transformation
#
# ------------------------------------------------------------------
def show_size_proc(page_obj_in):
	print(page_obj_in.artbox.lower_left)
	print(page_obj_in.artbox.lower_right)
	print(page_obj_in.artbox.upper_left)
	print(page_obj_in.artbox.upper_right)
# ------------------------------------------------------------------
def pdf_page_read_proc(pdf_file_in):
	pdf_file = open(pdf_file_in, 'rb')
	pdf_reader = PyPDF2.PdfReader(pdf_file)
	page_obj = pdf_reader.pages[0]
#
	show_size_proc(page_obj)
#
	return	pdf_file,page_obj
# ------------------------------------------------------------------
def pdf_merge_proc(page_obj_a,page_obj_b):
	deltx = 960
	delty = 1080
	page_obj_out = PyPDF2.PageObject.create_blank_page(width=deltx,height=delty)
	page_obj_out_bb = PyPDF2.PageObject.create_blank_page(width=deltx,height=delty)

	op = Transformation().translate(tx=0, ty=540)
	page_obj_out.merge_page(page_obj_a)
	page_obj_out.add_transformation(op)

	page_obj_out_bb.merge_page(page_obj_b)
	page_obj_out.merge_page(page_obj_out_bb) 
#
	show_size_proc(page_obj_out)
#
	pdf_writer = PyPDF2.PdfWriter()
	pdf_writer.add_page(page_obj_out)
#
	return pdf_writer
# ------------------------------------------------------------------
sys.stderr.write ("*** 開始 ***\n")
sys.stderr.write("PyPDF2.__version__ = %s\n" % PyPDF2.__version__)
pdf_in_a = sys.argv[1]
pdf_in_b = sys.argv[2]
pdf_out = sys.argv[3]
#
pdf_file1,page_obj_a = pdf_page_read_proc(pdf_in_a)
pdf_file2,page_obj_b = pdf_page_read_proc(pdf_in_b)
#
pdf_writer = pdf_merge_proc(page_obj_a,page_obj_b)
#
pdf_file1.close()
pdf_file2.close()
#
pdf_output_file = open(pdf_out, 'wb')
pdf_writer.write(pdf_output_file)
#
pdf_output_file.close()
#
sys.stderr.write ("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行コマンド
入力 in01.pdf (A4) in02.pdf (A4)
出力　out01.pdf (A3)

```bash
./pdf_merge_landscape.py in01.pdf in02.pdf out01.pdf
```

実行結果

```text
$ ./pdf_merge_landscape.py in01.pdf in02.pdf out01.pdf
*** 開始 ***
PyPDF2.__version__ = 3.0.1
(0, 0)
(960, 0)
(0, 540)
(960, 540)
(0, 0)
(960, 0)
(0, 540)
(960, 540)
(0, 0)
(960, 0)
(0, 1080)
(960, 1080)
*** 終了 ***
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.10.7
```

```text
>>> import  PyPDF2
>>> PyPDF2.__version__
'3.0.1'
```
MySQLインストール方法 + 基本コマンド一覧

## MySQLインストール （version指定なし）
```terminal
$ brew install mysql
```
**最新versionがインストールされます**

## MySQLインストール （version指定あり）
```terminal
$ brew install mysql@8.0
```
**ご自身の使用するversionに合わせて変更してください**

## MySQLのバージョン確認
```terminal
$ mysql --version
mysql  Ver 8.0.31 for macos13.0 on arm64 (Homebrew)
```

## MySQL起動
```terminal
$ mysql.server start
Starting MySQL
 SUCCESS! 
```

## MySQL停止
```terminal
$ mysql.server stop
Shutting down MySQL
.. SUCCESS! 
```

## MySQL再起動
```terminal
$ mysql.server restart
Shutting down MySQL
.. SUCCESS! 
Starting MySQL
. SUCCESS! 
```

## MySQLにログイン
```terminal
$ mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.31 Homebrew

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
```

## データベース作成
```sql
mysql> create database your_database_name;
```


## データベース一覧表示
```sql
mysql> show databases;
```

## データベースの選択
```sql
mysql> use your_database_name;
```

## テーブルの表示
```sql
mysql> show tables;
```

## SELECT
```sql
/* usersテーブルから全てのカラムを取得 */
mysql> select * from users;

/* usersテーブルを見やすく表示（※セミコロンなしで\Gとするとレコードの一覧が縦に表示されます）*/
mysql> select * from users\G

/* ユーザーテーブルから「id」と「name」カラムを取得 */
mysql> select id, name from users;
```

## WHERE
```sql
/* ユーザーテーブルから「name」が「michael」のレコードを取得 */
mysql> select * from users where name = 'michael';
```

## 比較演算子
```sql
/* ユーザーテーブルから「age」が「20以上」のレコードを取得（以上は20を含む）*/
mysql> select * from users where age >= 20
```

## LIKE演算子
```sql
/* ユーザーテーブルから「name」に「john」が含まれるレコードを取得 */
mysql> select * from users where name like '%john%';
```
※ john, johnson, johnathonなどが表示

## NOT演算子
```sql
/* ユーザーテーブルから「name」が「michael」でないレコードを取得 */
mysql> select * from users where not name = 'michael';
```

## IS NULL
```sql
/* ユーザーテーブルから「age」が「null」のレコードを取得 */
mysql> select * from users where age is null;
```
※「is null」ではなく「= null」だと正しく動かないので注意

## IS NOT NULL
```sql
/* ユーザーテーブルから「age」が「null」ではないレコードを取得 */
mysql> select * from users where age is not null;
```

## AND演算子
```sql
/* ユーザーテーブルから「first_name」が「michael」かつ「last_name」が「jackson」であるレコードを取得 */
mysql> select * from users where first_name = 'michael' and last_name = 'jackson';
```

## OR演算子
```sql
/* ユーザーテーブルから「first_name」が「michael」もしくは「last_name」が「jackson」であるレコードを取得 */
mysql> select * from users where first_name = 'michael' or last_name = 'jackson';
```

## ORDER BY
```sql
/* ユーザーテーブルの「age」を基準に小さい順で表示 */
mysql> select * from users order by age asc;

/* ユーザーテーブルの「age」を基準に大きい順で表示 */
mysql> select * from users order by age desc;
```

## LIMIT
```sql
/* ユーザーテーブルの「age」が「18」のレコードを「10件」取得 */
mysql> select * from users where age = 18 LIMIT 10;
```

## MySQLからログアウト
```terminal
mysql> exit
Bye
```
Laravel　Tailwindcss 【CDN】の参照

# Tailwindcss 【CDN】のまとめ。

# Add the Play CDN script to your HTML
```php
<script src="https://cdn.tailwindcss.com"></script>
```
# Try customizing your config
```php
 <script src="https://cdn.tailwindcss.com"></script>
```
# Try adding some custom CSS
```php
<script src="https://cdn.tailwindcss.com"></script>
```
# Try using a first-party plugin
```php
<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,line-clamp"></script>
```

https://tailwindcss.com/
【悲報】Oracleまたしても値上げ

## 何が値上げしたの？
Oracleの年次調整量(AAR)の比率が増加しました。

## 年次調整率　AARとは？

簡単に言えば、Oracleライセンスの**保守金額に加算される**料金のこと
毎年一定のAAR割合分を加算して年間保守料が増加していく。。
**つまり、以前から年々増加していたが増加率が更に上昇した**

> AARは Annual Adjustment Rate　の略
> 

> ※旧名称「サポート更新時調整料金制度（PA：Pirce Adjustment）」が2022年
7月より「AAR」に呼称変更されました。
> 

## いつから増える？

契約開始日が以下の期間に含まれるテクニカル・サポート契約が対象となります。

・2023年5月31日以前          ：AAR 4%
・2023年6月1日以降            ：**AAR 8%** ★New

## AARの計算式

前年の保守金額　×　(100% + AAR(%) )

> ※前年の保守金額を元に増加していくので、AARの数値が一定でも増加量は増えていく
[https://jpn.nec.com/soft/oracle/support_buy_attention.html](https://jpn.nec.com/soft/oracle/support_buy_attention.html) (外部リンク)
> 

このグラフでいうと青色のグラフがAARの計算方法を示しています。
複利の計算と同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117026/a9e0540a-7c95-3283-42b8-420175c7d6a4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3117026/aa115115-a510-2476-2e29-8a2e9b578f47.png)

**AAR8%の場合、9年で保守金額が二倍になる計算です**
ハイアウトプットマネジメントを読んだメモ

## この本について

ハイアウトプットマネジメントは1984年にインテル社のCEOであるアンドリュー・グローブが著した伝説的なマネジメント本。オライリーから出ている「エンジニアリングマネージャのしごと」や「エンジニアのためのマネジメントキャリアパス」からも参照されている。

## マネージャの行動・アウトプット

### マネージャの行動

マネージャの行動は下記に分類されるとしている。これはエンジニアリングマネージャのしごとの中でも紹介されている。

 - 情報収集: ミーティングやメールなどを通して情報を収集する
 - 情報提供: ミーティングやメールなどを通して情報を提供する
 - 意思決定: 決定を行う
 - ナッジング: 直接の配下や隣接する組織に対して意見を伝える
 - 役割モデル: 他の人にして欲しい動きを率先して行い規範となる

### マネージャのアウトプット

> 「マネジャーのアウトプットとは、その直後の監督下にあったり、または影響下にある組織体のアウトプットである」

直接の監督下にない、"影響下にある組織体"のアウトプットもマネージャーのアウトプットであると述べている。これは明確に意識できていないことが多い観点だと思う。
つまり、エンジニアから見たとき、機能別組織においては企画やデザイナーのような協働する(隣接する)組織への提言なども職責のうちだということ。

## 品質について

> 〝価値が最低の段階〟で在庫を維持するのがよい。また、価値が低ければ低いほど、一定の在庫コストに対して、生産面での柔軟性がそれだけ多く保てることになる。

ソフトウェア開発に置き換えるなら、なるべく作業を先送りすることに近いかもしれない。
ソフトウェア開発プロセスにおいては、要求分析、要件定義、設計、実装、テストのプロセスを経て付加価値が付く(工数がかかる)ので、必要だと確定するまで可能な限りやらない姿勢が大事ということになる。

> 製造業者が守るべき大原則は、顧客が満足するような品質レベルの製品を、できるだけ低いコストで顧客に引き渡すことである。

> 最低のコストで受容できる品質を得るには、欠陥材料をその蓄積価値が最も低い段階で拒否することが絶対に重要である。

要求分析、要件定義、設計、実装、テストの早い段階で問題を取り除ける仕組みが重要と言い換えることができる。

このあたりはソフトウェア開発でも当たり前のことではあるが、「早くリジェクトする」は生産の基本原理なのだなと思った。

## マネージャーのしごとについて

### テコ作用

> マネジャーは多くのボールを同時に空中に上げておき、自分の部門のアウトプットを最高に上げると思われる活動に自分のエネルギーと注意を注がなければならない。いいかえれば、自分の〝テコ作用〟が最大となりそうな点に移るべきなのである。

書籍内で "テコ作用" という言葉はさまざまな場所で大量に使われている。マネージャーは常にテコ作用を意識すべきだとアンドリューは考えているのだと思う。テコ作用については、知識の伝達、訓練、権限委譲などを例として何度も取り上げている。

### 権限委譲について

> 人は自分が精通している活動と、あまりよく知らない活動とのどちらを委任するかと言われたら、どちらを選ぶだろうか。
> (中略)
> よく精通していることのモニタリングのほうが容易だから、どちらかの選択をする場合は、一番よく知っている活動を委譲すべきである。

フォローしない権限委譲は職務放棄であり、モニタリングし仕事の完了に責任を持たなければならないと述べている。
プレイング・マネージャだと適材適所で作業分担したくなるだろうから胃の痛くなる話。

## ミーティングについて

> 私の活動、つまり、情報収集、情報提供、意思決定、ナッジング、役割モデルのうち、ミーティング以外でできるものはいったいどれだろうかと。答えは実際問題として、なし、なのである。ミーティングこそマネジャーとして活動する機会を提供しているのである。

> ピーター・ドラッカーは時間の25パーセント以上を会議で過ごすようなら、それは組織不全の兆候だと言っている。私ならこう言いたい──組織不全の真の兆候は、人が25パーセント以上の時間を、臨時に開かれる使命中心ミーティングで過ごすときに現われる、と。

アンドリューはミーティングについてとても肯定的で、会議の定例化を推奨している。定例化することで問題解決をバッチ処理できるようになり、会議外での割り込みを減らすことができるといったメリットをあげている。
定例ミーティングが多いとげんなりするけど、確かにバッチ化できるっていうメリットは大きそう。

## 組織について

> ミドル・マネジャーがこの高いテコ作用を有する仕事に成功するには、２つのことが必要である。まず、会社活動に従事するつもりならば、ハイブリッド組織が不可避なものであることを認めなければならない。第二に、ハイブリッド組織を運営していくのに必要な実際上のやり方を開発し体得していかなければならない。これが次章の主題となる〝二重所属〟制度である。

適切な意思決定や効率性のバランスを考えると、どうしてもここに行き着くとアンドリューは述べている。ハイブリッド組織とは機能別組織と使命中心の組織(事業やプロダクト別の組織)を組み合わせた組織のこと。マトリクス組織とは別の概念だが、書籍内ではそれに近い話も出てくる。
完全な機能別組織と指名中心の組織、そしてマトリクス組織も経験しているけど、混乱はあれどもマトリクス組織のようなハイブリッドな方が良いと感じる。1984年に既にこういった知見がインテル社のCEOによってパブリックなものになってたとは。

## まとめ

古い本ではあるが、今でも通用する考え方で色褪せない内容。とはいえ「エンジニアリングマネージャのしごと」や「エンジニアのためのマネジメントキャリアパス」の方がエンジニアスペシフィックで具体的なので、エンジニア的には「エンジニアリングマネージャのしごと」や「エンジニアのためのマネジメントキャリアパス」の副読本くらいお気持ちでいいかも。
Salesforce 名前空間の作成 (PBOを使って)

Salesforce の `名前空間` の作成手順をメモします。
ここでは 名前空間を作成して PBO の `名前空間レジストリ` にリンクするまでの手順が該当します。

# 前提

- 基本的な Salesforce 操作ができること
- Partner Business Org (PBO) が使用可能であること
- PBOなどの環境が一式整備済みであること

# 手順

## 名前空間で利用する Developer Edition の作成

### Partner Business Org (PBO) ログイン

Partner Business Org (PBO) にログインします。

### 組織を作成

- `環境ハブ` (Environment Hub) を開く
- `組織を作成` をクリック
- 組織を作成画面に次の情報を入力

| 項目 | 値 | 補足 |
| --- | --- | --- |
| 目的 | 開発 |  |
| (以下を使用して作成) | Standard Edition |  |
| エディション |  Partner Developer |  |
| 組織名 | 例: `pabcd12` | わたしは 'p' プレフィクス付き  + 文字 + 数字2桁のサフィックスとしました |
| 私のドメイン | 例: `pabcd12` | 組織名 |
| ユーザ名 | 例: メールアドレス `.` `pabcd12` | メールアドレス + `.` + 組織名 |

- `作成`をクリック

### PBO から一旦ログアウト

PBOから一旦ログアウトします。

## 作成した Developer Editon に名前空間を作成

### 作成した Developer Edition にログイン

- メールが届くのを待つ
- 作成した Developer Edition にログイン
    - 使用するのは 例の `pabcd12` に相当する組織
- `パッケージマネージャ` を開く
- `名前空間設定` の `編集` をクリック
    - 参考: 名前空間の名称には、`abcdtest02` のように、私は全て小文字を使用しています。
- `確認` をクリック
- `保存` をクリック

### 作成した Developer Edition からログアウト

名前空間用の Developer Edition からログアウトします。

## PBO に名前空間を紐付け

### Partner Business Org (PBO) ログイン

Partner Business Org (PBO) にログインします。

### 名前空間レジストリに名前空間をリンク (PBOからのアクセスを許可)

- `名前空間レジストリ` を開く
- `名前空間をリンク` をクリック
- 名前空間で利用する組織の認証情報を入力
    - 例: メールアドレス `.` `pabcd12` でログイン
- `アクセスを許可しますか?` で `許可' をクリック。

# まとめ

- これで 新しく名前空間を作成して PBO へのリンクまで終わりました。
- 多くの場合、このあと 名前空間をもちいて パッケージ作成や AppExchange アプリ作成などをおこなうことでしょう。
JavaScriptコードメモ。

1. ランダムな数値を出す。

```javascript
const numbers = [1, 2, 3, 4, 5];

for(let i = 5; i > 0; i--){
  const randomNum = Math.floor(Math.random() * i);
  let tmp = numbers[i - 1]; 
  numbers[i - 1] = numbers[randomNum]; 
  numbers[randomNum] = tmp;
}
```
PHP コードメモ。

1. 日付を出す。
```php
date_default_timezone_set('Asia/Tokyo');

for ($i=0; $i<366; $i++):
    $time = strtotime( $i . ' day');
    $day = date('n/j(D)', $time);
    echo $day . '<br>';
  endfor
```
2. 曜日を出す。
```php
$week_name = ['日', '月', '火', '水', '木', '金', '土'];

date_default_timezone_set('Asia/Tokyo');
$week = date('w');
echo "今日は$week_name[$week]曜日です。";
```
Python Pillowによる連番画像の作成

# 概要
　会議資料の右上によくある
![image0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13818/4a51cdf5-1a5d-96ef-04ca-1305506bb6d0.png)
みたいものをまとめて作成します。
　作成した資料番号の画像を、PDFに貼り付けると会議資料の完成です。

# コード

```python
from PIL import Image, ImageDraw, ImageFont

# PCローカルのフォントへのパスと、フォントサイズ(20)を指定
font = ImageFont.truetype('C:/Windows/Fonts/meiryob.ttc', 20)

def drawing(number, label):
    x = 30 # 縦
    y = int(len(label)*10) + len(str(number)) + 90 # 横

    # RGB, 画像サイズ, 背景色を設定
    im = Image.new("RGB", (y, x), (256, 256, 256))
    draw = ImageDraw.Draw(im)
    text = label + str(number)

    # 描画位置、描画する文字(改行は\n)、文字色、フォントを指定
    draw.multiline_text((20, 0), text, fill=(26, 39, 146), font=font, anchor=None)
    
    # 枠線の幅色
    draw.rectangle([(0, 0), (y, x)], fill = None, outline="#000000", width = 3)
    # draw.rectangle([(0,0), (140,30)], fill = None, outline="#000000", width = 3)

    # ファイルに出力
    im.save("./" + label + str(number) + ".png")

# 個数と、接頭辞を指定
for i in range(12):
    drawing(i, "資料")
```
（小ネタ）知らん間にmacOSでフルスクリーン時にメニューバーを常時表示できるようになっとる

# やりかた

macOS Montereyならみんなできるはず？

1. システム環境設定
1. Dockとメニューバー
1. フルスクリーンでメニューバーを自動的に表示/非表示

こんな項目あったっけ…


## その後
Dockのサイズが規定値内に戻されるので

```zsh
defaults write com.apple.dock largesize -int 256 | killall Dock
```

しよう

https://qiita.com/Soluna_Eureka/items/b4db36d66227aaa69fe1




# MacBook Pro 2016 Late終了のお知らせ
ついにVenturaからこの世代がサポートを打ち切られた
2018年に有楽町ビックカメラで10万くらい安く売られてたのを現物で買ったUSキー持ちの正規品
ディスプレイもスピーカーも元気だけどキーボードは完全に壊れちゃったので外付けを使っている
最近は起動が遅くディスクもヤバい，次どうしようか，M2 Airは為替がアレだしMacはSSD高い…
（intelチップ2016 Late世代でもtouch barつきモデルはSSDの換装はできないらしいので）
Docker Desktop for Macが遅いので早くしてみた

# 概要
これまで「MacでDockerを利用すると遅い」というのが一般認識だったと思います。
そのため、以下のような涙ぐましい努力をしてきたことと思います。

- `node_modules`や`vendoer`などのPHPやNodeのライブラリをホストとマウントしないようする
- マウントするvolumeに`cached`や`delegated`のオプションを付ける
- ボリュームをrsyncで同期する
- Linuxサーバーを用意してリモート開発する
- Vagrantで作成した仮想環境内でDockerを利用する

しかし、これらの努力は全て過去のものと化しました！(言い過ぎです。笑)

# 環境
- macOS Ventura 13.2
- プロセッサ 2.8 GHz クアッドコアIntel Core i7
- Docker Desktop v4.16.2

# 解決法
Docker Desktopの設定で`gRPC FUSE`(デフォルト)から`VirtioFS`に変更するだけです。

## VirtioFSとは？
VirtioFSとは、公式サイトにあるように、仮想マシンとホストとの間で共有できるファイルシステムです。
今までのファイルシステムだと仮想環境での使用に対し最適化されておらずパフォーマンスに影響が出ていたようです。

公式サイト：https://virtio-fs.gitlab.io/

## 設定手順
1. Docker Desktopを起動
1. 「設定アイコン」 => 「General」を開く
1. file sharingを`gRPC FUSE`から`VirtioFS`に変更
1. 「Apply & restart」をクリック

![スクリーンショット 2023-02-01 11.57.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290840/e0549d74-4350-188b-1a96-e1bd15d48af2.png)

# 検証
## 検証内容
https://qiita.com/A-Kira/items/5ce3e1bff34e179ebbc2

上記環境で`node_modules`を削除し、`yarn`を実行して、nuxt構築のために必要なnodeパッケージをインストールする時間を計測します。


## 結果

|  |1回目 | 2回目 | 3回目 | 平均 |
|:-:|:-:|:-:|:-:|:-:|
| gRPC FUSE  | 150.65s  | 177.35s  |  144.08s | 157.36s  |
| virtiofs  |  137.33s | 132.69s  | 66.69s  | 112.24s  |

平均値で約45s早くなったという感じですね。

# 最後に
今回の検証はプレーンなNuxt3環境でのテストでしたので、もっと開発が進み利用するパッケージが増えたり、ソースコードが増えたりした環境だともっと恩恵を感じられそうな気がしますね。
Docker × Macの開発環境で苦痛を感じている方はぜひ一度試してみてください。

# 参考
- [【超重要な追記あり】Docker Desktop for Macを使ってる人はみんな今すぐvirtiofsを使うんだ！](https://www.keisuke69.net/entry/2022/03/25/083002)
- [Docker Desktop for Mac使いを照らす一筋の光　virtiofs](https://nextat.co.jp/staff/archives/271)
WSL2にてneovimのプラグイン管理

# 背景
- 現在急激に流行ってきているといわれるneovimのinit.vimをluaで記述する方法を取り入れたかった
- 研究室のPCがwindowsなのでWSL2ベースでやる必要があった

# neovimのインストール
- 以前からneovimを使っていたが，init.luaを読み込まなかったため0.5系以上にする必要があった
## 最新のneovimをインストール
まずはneovimのリポジトリを追加
```sh
sudo apt-add-repository ppa:neovim-ppa/stable
sudo apt update
```
neovimのインストール
```sh
sudo apt install neovim
```
これでinit.luaを読み込めるようになる

# init.luaについて
init.vimをluaで記述したもの
init.vimと共存はできない．どちらも存在するとエラーが出るらしい
自分の `~/.config/nvim`は以下のようになっている
```sh
.
├── init.lua
└── lua
    ├── plugins.lua
    └── settings.lua

1 directory, 3 files
```
init.luaにすべて記述するのではなく，`/lua`以下にsettingsやpluginsなどに分けて記述することで後から見やすくする
    init.luaでrequireするときは.luaをつける必要はない
```lua:init.lua
require "plugins"
require "settings"
```

# packer.nvimの導入
まずはクローンしてくる
```sh
git clone https://github.com/wbthomason/packer.nvim \
  ~/.local/share/nvim/site/pack/packer/opt/packer.nvim
```
`init.lua`を上記のようにし，`/lua/plugins.lua`を以下のようにする（ほとんどコピペ）
プラグインを追加したい場合はuseの後に追加する
```lua:plugins.lua
vim.cmd[[packadd packer.nvim]]

require("packer").startup(function()
  -- 起動時に読み込むプラグインは名前を書くだけです
  use "tpope/vim-fugitive"
  use "tpope/vim-repeat"

  -- opt オプションを付けると遅延読み込みになります。
  -- この場合は opt だけで読み込む契機を指定していないため、
  -- packadd コマンドを叩かない限り読み込まれることはありません。
  use { "wbthomason/packer.nvim", opt = true }
  -- packer.nvim 自体を遅延読み込みにする理由はまた後ほど。

  -- コマンドを叩いたときに読み込む。
  use { "rhysd/git-messenger.vim", opt = true, cmd = { "GitMessenger" } }

  -- 特定のイベントで読み込む
  use { "tpope/vim-unimpaired", opt = true, event = { "FocusLost", "CursorHold" } }

  -- 特定のファイルタイプのファイルを開いたら読み込む
  use { "fatih/vim-go", opt = true, ft = { "go" } }

  -- 特定のキーを叩いたら読み込む
  -- この例ではノーマルモードの <CR> にマッピングしていますが、
  -- モードを指定する場合はテーブルを入れ子にします。
  -- keys = {
  --   { "n", "<CR>" },
  --   { "v", "<CR>" },
  -- }
  use {
    "arecarn/vim-fold-cycle",
    opt = true,
    keys = { "<CR>" },
  }

  -- 特定の VimL 関数を呼ぶと読み込む
  -- この例だと、任意の場所で Artify("hoge", "bold") のように呼び出された時に、
  -- このプラグインも読み込まれます。
  use { "sainnhe/artify.vim", opt = true, fn = { "Artify" } }

  -- 実は opt = true は省略できます。読み込む契機（この例では cmd）を指定すると、
  -- 自動的に遅延読み込みとみなされます。
  use {
    "npxbr/glow.nvim",
    cmd = { "Glow", "GlowInstall" },
    -- run オプションを指定すると、インストール時・更新時に
    -- 実行するコマンドを指定できます。
    run = [[:GlowInstall]],
    -- 先頭に : がついていないなら bash -c "..." で実行されます。
    -- run = [[npm install]],
    -- 関数も指定可能です。
    -- run = function()
    --   vim.cmd.GlowInstall()
    -- end,
  }

  -- 条件が真の時のみ読み込みます。条件は起動時に毎回判定されます。
  use {
    "thinca/vim-fontzoom",
    cond = [[vim.fn.has"gui" == 1]], -- GUI の時のみ読み込む。
    -- 関数も指定できます。
    -- conf = function()
    --   return vim.fn.has "gui" == 1
    -- end,
  }

  -- 依存関係も管理できます。vim-prettyprint は capture.vim に依存しています。
  use {
    "tyru/capture.vim",
    requires = {
      { "thinca/vim-prettyprint" },
    },
  }
end)
```
## プラグインインストール
`plugins.lua`にプラグインを追加したら，nvimを起動して
```
:PackerInstall
```


# 参考文献
https://sig9.org/archives/3148
https://qiita.com/delphinus/items/8160d884d415d7425fcc
気軽にはじめるElixir 〜Livebook App〜

Elixirを始めたい人で気軽にローカルで実行する環境手順です

# Windows & Mac 共通事項

https://livebook.dev/#install

↑のリンクからダウンロードしてください
MacまたはWindowsを選んでダウンロードしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/867941a3-d5c3-48b0-8b71-2cc7474dd08f.png)

# Windows

ダウンロード時に一般的にダウンロードされませんと表示するため
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/560c0aea-bc0e-0e8d-464c-5c81a929e9fe.png)


「...」をクリックして「保存」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/f38accd1-be55-1429-4305-07e429ac0903.png)

「詳細表示」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/c939f1c2-5707-6441-c411-751a3f0e1ae6.png)

「保持する」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/af862d2f-0a55-e1ce-195c-530e20afce96.png)

「ファイルを開く」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/6c655fe6-a4b8-1174-7ee0-40810e1cf776.png)

「はい」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/3c35504a-0ab7-d295-cf5b-1e0a36c04de2.png)

「Install」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/1c407009-0098-9863-3705-2e804b2aa27c.png)

しばらく待ちます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/55976ca0-c824-ae56-02d2-82be2e50dfd2.png)

「Close」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/92416da0-e9d3-5c83-ce94-aca3f0867e09.png)

デスクトップにLivebookのアイコンがあるので、ダブルクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/387da712-b482-857e-e568-34672a2fa17e.png)

Livebookが起動できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/4e8ff232-f8f9-ca6b-7af3-ba23c7a6dfc7.png)

# Mac
Livebookダウンロード時に下記のメッセージが表示するので「許可」をクリック(Safariの場合)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/dd6570dd-ecd9-b6d0-add5-987a4c2d7090.png)

Dockからダウンロードしたファイルをダブルクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/a8239122-4e63-3a69-d11f-c27d5158afab.png)

LivebookのアイコンをApplicationsにドラッグする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/01331be3-dbda-2110-c6bb-d00475a4c2bc.png)

LauncpadからLivebookをダブルクリック
![remmina_Mac__20230201-030254.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/955d4d06-15e1-8c44-491a-4e57e9ad404b.png)

「開く」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/41714ff7-b678-3c71-33e5-ce99b6a556ab.png)

Livebookを起動することができました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/2cd4589f-9e37-acf3-7ff2-50f58cd4c257.png)

# 共通　Livebookをいじってみよう

「New notbook」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/fb33b614-953e-f764-22d0-8b63cf2ecbaa.png)

Sectionに「1 + 1」と入力してShift + Enterをする
2と表示されました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/760536f8-dc6d-7b27-8a32-9cdae352f433.png)
【個人開発】初心者によるOpenAI APIの費用とアプリ設計


# はじめに
初心者がWebアプリを作ってみたよ

https://qiita.com/kajiyai/items/9b1418d21a55cd5dbc5d#tips

APIにお金がかかるので使用制限についても考えてみたよ
> 本記事

作ったアプリ

https://episode-title-generator.vercel.app/

# OpenAI APIの費用

## 画像

|画像サイズ  |ドル  |円 |
|---|---|---|
|1024*1024  |0.020  |2.60  |
|512*512  |0.018  |2.34  |
|256*256  |0.016  |2.08  |


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/bc059552-cdfb-2b7e-1463-26db6b9b681c.png)

### テキスト

|モデル |ドル  |円 |
|---|---|---|
|Ada  |0.0004  |0.052 |
|Babbage  |0.0005  |0.065  |
|Curie  |0.0020  |0.26  |
|Davinci  |0.0200  |2.60  |


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/c4a94b4d-3da3-6a3a-8487-e219cd8d4e05.png)

当然、性能の高いモデルはコストも高いです。
表の金額は1000トークン当たりの金額です。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/8f38f63d-c011-f449-0d40-7c823f03a0dd.png)


(2023/02/01時点 130円/ドル計算)
出典: https://openai.com/api/pricing/


# 私の例

![episode-title-generator.vercel.app_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/ab516d5c-5f10-873c-bf97-bbbf819c7044.png)

3回APIを使う場面がある

- 入力→出力
    1. キーワード→タイトル(テキスト)
    1. タイトル→画像生成用プロンプト(テキスト)
    1. プロンプト→画像(画像)

モデルはDavinciを使ってます

テキストはopenai提供のtokenizerシュミレータで計算できる

https://platform.openai.com/tokenizer

## キーワード→タイトル(テキスト)

テキストを補完する用途で使う場合、**入力文字列のトークンと出力文字列のトークンの合計**で課金される模様

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/a0e06fbb-5048-38bf-0bb3-98cde9c9b0dc.png)

入力
入力キーワードにもよるが、おおよそ75トークン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/8fe6c47b-2be4-55ef-41d6-cde09f7b128c.png)


出力
時々ノイズが入るが、おおよそ50トークン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/86f56430-8ceb-8b52-719d-f9c06a311688.png)


合計
おおよそ130トークン程課金される


## タイトル→画像生成用プロンプト(テキスト)

入力
おおよそ160トークン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/38824922-d794-a78f-25c2-f7451fd91744.png)


出力
おおよそ100トークン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/52282be0-d7d0-5f59-56a2-9dfe1d518c73.png)

合計
おおよそ260トークン

## プロンプト→画像(画像)

256*256サイズで出力しているため、1枚2.08円


## 費用まとめ


- 1回当たりの費用感
    -  キーワード→タイトル(テキスト)
        - 130トークン:0.02*130/1000=$0.0026(**0.368円**)
    - タイトル→画像生成用プロンプト(テキスト)
        - 260トークン:0.02*260/1000=$0.0052(**0.736円**)
    - プロンプト→画像(画像)
        - $0.016(**2.08円**)


## 設計

openai登録すると初回登録得点で18ドル(2340円)分のクレジットが付与されます。(太っ腹..
開発に3ドルほど使ったので、15ドルほど残ってます(2023/02/01時点)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/46ad8211-8554-f748-8df0-7b956895936f.png)



上記の費用を元に1日の使用上限を決めました。(どれくらい使ってくれるか分からないので)

ずばり、ボタンを押せる回数を**1日100回**に設定しました。

具体的にはサーバーレスDBのplanetScaleを使用し、OpenAIのAPIからのレスポンスを全てDBに格納し、アクセスのたびにレコード数を数える、というやり方を採用しました。


100回使用されてかかる費用の事例を想定して計算してみた1日の費用感

- 最小
    - タイトル生成を100回
        - 0.368*100=**36.8円**
- 最大
    - タイトル生成1回
        - 0.368*1 = 0.368円
    - プロンプト生成1回
        - 0.736*1 = 0.736円
    - 画像生成98回
        - 2.08*98 = 203.84円
    - 合計
        - 0.368+0.736+203.84=**204.944円**
【Laravel】指定したプライマリーキー持ってるレコード無かったら新しくモデルオブジェクト作るよfindOrNew

## 概要

外部から受け取ったidでfindして無かったら新しくモデルオブジェクトを生成したいな。

```php
$hoge = Hoge::find($hogeId) ?? new Hoge();
```

findなんちゃらみたいな同じような事が出来るメソッドあるんじゃねえか?補完で見てみるか

Hoge::fin...お？

![スクリーンショット 2023-02-01 12.01.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/9fdb35cc-301e-2109-ec38-fe6aa3576e3a.png)

あるじゃねえか！！!

https://readouble.com/laravel/8.x/ja/eloquent-relationships.html

![スクリーンショット 2023-02-01 12.04.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282328/a28e513c-a5d6-77d5-c478-c539eff0b47d.png)


詳細には書かれてませんがまぁ名前からなにするかは想像出来るので良いですね。

隣に書いてあるfirst~系はこの記事が参考になりそうです。

https://qiita.com/sussan0416/items/eee8852269ac862669d9
[JavaScript]ゴルトンボードを検証するプログラムを作ってみた

ゴルトンボードとは、二項分布から正規分布への近似を表現する確率シミュレーションです。
画像のように右か左に1/2の確率で落ちる釘を用意し、最終的にどこに落ちるかを検証します。

![180px-Galtonbrett_mathe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706631/4626426f-3251-dae0-2c88-4ac4e045c62f.png)


https://ja.wikipedia.org/wiki/%E3%82%B4%E3%83%AB%E3%83%88%E3%83%B3%E3%83%9C%E3%83%BC%E3%83%89

このプログラムをJavaScriptで作成してみました！


```
const row = 10;
const ball = 10000;
let array = [];

// とりあえずボール一個の時
let posi = () => {
  var position = 0;
  for (let i = 0; i < row; i++) {
    let randomValue = Math.floor(Math.random() * 2);
    position += randomValue;
  }
  return position;
};

// positionをボール分配列で出す
for (let i = 0; i < ball; i++) {
  array.push(posi());
}

console.log({ array });

// arrayの出力結果をどこにボールがいくつ入っているかという配列に変える
let ans = Array(row).fill(0);

// row分調べる
for (let i = 0; i < row + 1; i++) {
  ans[i] = array.filter((n) => n === i).length;
}

console.log({ ans });

```

結果
```
{
    "ans": [
        12,
        97,
        476,
        1152,
        2103,
        2392,
        1995,
        1194,
        456,
        113,
        10
    ]
}
```

なんとなく正規分布に近い出力結果が得られました！
パチンコなんかもこの理論を応用して作られてそうですね！

つまり、釘の数からパチンコの台が当たる期待値なんかも調べられそうです！

もっと良いコードを思いついた人などがいたらぜひコメントください！
Jetpack ComposeでOSのアラーム設定を開きたい

参考
==
https://developer.android.com/reference/android/provider/AlarmClock#ACTION_SHOW_ALARMS

`AlarmClock.ACTION_SHOW_ALARMS`
というActionでIntentを作成してstartActivity

コード
==
```kotlin
import android.content.Intent
import android.provider.AlarmClock
..
省略
..
            val intent = Intent(AlarmClock.ACTION_SHOW_ALARMS)
            if (intent.resolveActivity(context.packageManager) != null) {
                context.startActivity(intent)
            }

```

AndroidManifestに追記が必要
```xml
    <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
```
AWS Lambda(node.js)でyoutube APIを利用してJSON作成した話

## どんな記事
・AWSを使ってyoutube APIにアクセスするLambda関数を作成したときのお話
　node.jsの作成例が少なかったのでこんな感じでうまくいったよが伝われば・・

## 利用技術
・AWS Lambda
・AWS S3
・youtube-node(youtube API) ※google developerに登録する
・node.js 16

## 前提条件
・node.js 16での開発

  パッケージのインストール
```
 npm install youtube-node
 npm install aws-sdk
```

## 作成したコード（抜粋）
```
const AWS = require('aws-sdk');
const s3 = new AWS.S3({'region':'＜地域＞'});

const Youtube = require('youtube-node');
const youtube = new Youtube();

exports.handler = function(event, context, callback) {

    // キーワードはLambdaの引数に設定(json形式)
    var keyword = event['q'];
    var limit = 50;

    youtube.setKey('＜developer登録したときにゲットしたkey＞');

    // 細かい設定 (youtube API仕様書参照)
    youtube.addParam('order', 'date');
    youtube.addParam('type', 'video');
    youtube.addParam('regionCode', 'JP');

    // 検索の実行
    youtube.search(keyword, limit, function(err, result) {
        items = result["items"];
        for (var i in items) {
            //検索結果からjsonを新しく作成する
            //作成したjsonをS3へ配置する(s3.putObject)
        }
    })
};
```
## 作業内容
1.AWS Lambdaで関数の作成（任意の名前）

2.作成したコードをアップロード（zipでOK)

3.キーワードをイベントJSONに追加してテスト
```
{
  "q": "検索キーワード"
}
```
4.テスト結果成功！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215997/e3f565bd-23bc-dbeb-cf9e-3617df8347e6.png)

## まとめ
youtube API 自体がkeyさえあればインターネットを通してアクセスが可能なので結構簡単にできた。
youtubeに関してLambdaの参照の設定などは特に必要なかった。
※S3に配置するための関数の許可の設定は必要。
SAP GUI for Windows 8.00のインストール

SAP GUI for Windows 8.00がリリースされたので早速インストールしてみました。

マテリアル番号は50160634ですので、検索してください。
ZIPファイル形式なので、展開します。

8.00からは32bit/64bit版がリリースされます。
インストーラのパスが異なるので気をつけましょう。
32bit: "SAP_GUI_for_Windows_8.00_Comp._1_\PRES1\GUI\Windows\Win32\Setup\NwSapSetup.exe"
64bit: "SAP_GUI_for_Windows_8.00_Comp._1_\PRES1\GUI\Windows\Win64\Setup\NwSapSetup.exe"

インストーラを起動してからの流れは今までとほぼ同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/3f482ff5-c716-21b7-0ac6-6611b23c0659.png)


私のPCにはGUI7.70が入っていたのですが、64bit版8.00にアップグレードはできないそうです。
64bit版を入れたい方は、事前にアンインストールが必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/c259987e-0d01-8955-6843-5df9ed0741b1.png)

GUIのエントリが引き継がれるか、テスト用にエントリを入れてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/2d774e53-e59f-6640-c95e-86c0b1abab89.png)

旧GUIのアンインストールは設定→アプリと機能からアンインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/3eba914e-cee6-b415-5111-144caa31833d.png)

改めて、8.00 64bit版のインストールを再開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/4b0ac6af-4056-eb45-b917-407459967b32.png)

毎度インストールコンポーネントは悩みますが、今回はいろいろ入れてみました。
KW Add-OnとAutomatic Workstation Updateは明確に使わないので外しました。
一般的には、一番上の"SAP GUI for Windows 8.00"だけで問題ないです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/af974f9c-5c2d-5be3-0407-7c33cdb8d056.png)

追加コンポーネントを選ぶと、インストールパスを確認されます。デフォルトのままでインストールします。変更したい場合は変えてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/5a4444ab-5618-b178-fd8b-52fe5d6d2c7b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/139ba758-257b-dd13-8118-70c5390c18f2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/11343895-6a55-59fe-6a92-cf0505135e94.png)

最後に再起動要求がきて完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/0b811df7-80dd-b2d0-dfb9-8808b80322ad.png)

左が8.00、右が7.70ですが、アイコンが新しくなっています。
ラインが中に入ってますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/21bf2a34-72e0-ca61-c6a4-bfe8de56d57c.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/403e5a20-8c9e-2df8-15c8-b42192c59b2d.png)

起動してみたら、無事にGUIのエントリは引き継がれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/b2ae0405-0e0e-847b-3c44-bea8d411eb73.png)


余談ですが、メディアの中のガイドを漁っていたら、ヘッダにSAP NetWeaver 8.00の記載がありました。
7.5の次は8.00になるのかな。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2587098/3b0ddf38-82ba-6711-6a67-c8c545707850.png)
Ruby　配列を使ったプログラムの作成

# each_with_index
each_with_indexはRubyに標準で組み込まれているメソッドです。
繰り返し処理をしながら、その要素が何番目に処理されたのか、表示することができます。

```ruby
配列名.each_with_index  do |item, i|

end
```

例
```ruby
animals = ["ねこ", "とり", "うさぎ"]

animals.each_with_index do |animal, i|
  puts "#{i + 1}番目の動物は、#{animal}です"
end
```

```
1番目の動物は、ねこです
2番目の動物は、とりです
3番目の動物は、うさぎです
# ターミナル出力
```

配列は0番目から始まるため、#{i + 1}としています。

# searchメソッドとeach_with_indexメソッドを組み合わせてプログラムを作る

```ruby
def search(target_num, input)

  input.each_with_index do |num, i|
    if num == target_num
      puts "#{i + 1}番目にあります"
      return
    end
  end
  puts "その数は含まれていません"
end

input = [2, 4, 6 ,8, 10, 12, 14, 16, 18, 20]
search(10, input)
```

↓配列inputを定義しています。<br>
input = [2, 4, 6 ,8, 10, 12, 14, 16, 18, 20]

↓searchメソッドを呼び出しています。10と変数inputは実引数。
search(10, input)

1行目、呼び出されたsearchメソッドでは、target_numとinputを借り引数として受け取ります。

input.each_with_index〜内での処理
配列inputに格納されている要素を１つ一つnumとして取り出し、要素ごとに当てられている添字をindexで取得します。
if文でnumとtarget_numが等しいと、「○番目にあります」とターミナルで出力されます。
returnでそのメソッドを終わらせます。
プロファイルと DevOps センター

[DevOps Center まとめに戻る](https://qiita.com/Keiji_otsubo/items/3969e9a6c09cf727a4d9)


+ [PSA: Profiles and DevOps Center](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000NFNlQSAX)

DevOps Center チームは、そのツールを使用してプロファイル メタデータを使用または管理することをお勧めしません。また、プロジェクトの .forceIgnore ファイルにメタデータを追加して、プロモーション/デプロイでプルまたはプッシュされないようにすることを具体的に提案します。 

# 何故？

fdx deploy-retrieve ライブラリ、sf CLI、メタデータ API などを使用する場合、それらが最下位レベルでどのように構成されているかにより、プロファイルのアクセス許可を上書きするという問題に遭遇します。DevOps センターもこのリストの例外ではありません。CLI チームは、ここでプロファイルのアクセス許可の問題について説明します。2 週間前の時点では、プロファイル メタデータ タイプの「サポート終了」のため、今後は対処されないことを全員に知らせてください。これが、プロファイルをパーミッション セットに分割することをベスト プラクティスとして提案する理由でもあります。これについては、パーミッション チームによるこの投稿で詳しく説明しています。  

DevOps Center を使用してプロファイルを管理する場合は、基礎となるプロファイル メタデータと API に関連する前述の問題が原因で成功しない可能性が高いため、これを行うことはお勧めしません。プロファイルをコミット/変更することは引き続き可能であり、その機能を明示的にロックアウトすることはありませんが、これらの理由により、今後はプロファイルに起因する問題のトラブルシューティングやサポートは行いません。 

+ [項目の作成時にプロファイルではなく権限セットで項目の項目レベル セキュリティを設定する](https://help.salesforce.com/s/articleView?id=release-notes.rn_forcecom_fls_permsets.htm&release=240&type=5)
+ [Dreamforce 2022 で約 25 分の PermissionSet 移行ツール/サポートについて語る](https://www.salesforce.com/plus/experience/Dreamforce_2022/series/Administrators/episode/episode-s1e6)
【Pyinstaller】MacOS用、Windows用のexeをそれぞれ作成する失敗しない方法

# はじめに
**Pyinstaller**を使ったPythonスクリプトのexe化方法を紹介します。
Pyinstallerは、Macで動かす場合はMacOS上で作成、WindowsならWindows上で作成、というように、**動かしたいOS上でそれぞれ作成する必要**があります。
それぞれのOSで失敗せずに作成できるコマンドなども合わせてご紹介します。

# exeを作成する
### 1. 仮想環境を作成する
Pyinstallerでexe化する際、仮想環境外でexe化をするとPC上にpipでインストールされている全てのライブラリを含んでしまいます。仮想環境でexe化することで、軽量なexeファイルを作成できます。

ディレクトリ構成は以下のようにします。
```
MyProject
 └─ my_app
     └─app.py  <--exe化対象のスクリプト
```

ターミナルでMyProjectに移動し、仮想環境を作成します。
```terminal: terminal
$ cd MyProject
$ python -m venv .venv
```

`MyProject`直下に`.venv`が作成されたことを確認してください。
```
MyProject
 └─.venv
     ├─Include
     ├─Lib
     └─Scripts
 └─ my_app
     └─app.py  <--exe化対象のスクリプト
```

### 2. Pyinstallerをpipでインストールする
仮想環境に入ります。
```terminal: terminal
MacOSの場合
$ source .venv/bin/activate

Windowsの場合
$ .venv¥Scripts¥activate

仮想環境に入ると以下のようになります。
(.venv) C:xxx/MyProject>
```

Pyinstallerをインストールします。
```terminal: terminal
$ pip install pyinstaller
```

他にスクリプト内で使用しているライブラリがある場合は、そちらも全てインストールします。
`requirements.txt`を使用すると、一括でインストールすることができます。（ここでは説明を割愛します。調べるとやり方が出てきますので、見てみてください）
```terminal:temrinal
pipでひたすらインストール
$ pip install aaaaa
$ pip install bbbbb
:
:

requirements.txtで一括インストール
$ pip install -r requirements.txt
```

### 3. Pyinstallerでexe化
#### MacOSの場合
```terminal:terminal
$ pyinstaller -F my_app/app.py
```

#### Windowsの場合

```terminal:terminal
$ pyinstaller my_app¥app.py --onefile
```

`successfully`の文字が最後に出たら、exeの作成成功です！