OmniAICreator/Qiita-1.07M huggingface dataset:
JSF入力チェック

# bootstrap-5-jbvalidator

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106550/208dfb37-d39d-acc8-5ab0-342af72f9b9a.png)

```.html
<h:inputText id="userId" value="#{loginManagedBean.userId}" 
  p:required="true" p:data-v-min-length="2" p:data-v-max-length="10"
  styleClass="form-control" />
```

```.js
$(function () {

    let validator = $('form.needs-validation').jbvalidator({
        errorMessage: true,
        successClass: true,
        language: 'static/lib/bootstrap-5-jbvalidator/lang/ja.json'
    });

    $("form").on('submit', function (e) {
        console.log('validator.checkAll()', validator.checkAll());
        if(validator.checkAll() > 0){
            // チェックエラー時はsubmitをキャンセル
            return false;
        }
    });

});
```

# bean validation

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106550/6a69058a-eff8-a532-0964-17d6efc63d6d.png)

```.html
<h:inputText id="userId" value="#{loginManagedBean.userId}" 
  styleClass="form-control" />
<h:message for="userId" styleClass="text-danger"></h:message>
```

```.java
@Named
@ViewScoped
@Getter
@Setter
public class LoginManagedBean implements Serializable {

    /**
     * ユーザID
     */
    @NotEmpty
    @Min(5)
    private String userId;
```

# 業務ロジックチェック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106550/8f6b6f76-b370-2d32-6571-62cf43bb3992.png)

```.html

<h:messages globalOnly="true" style="list-style:none" 
  styleClass="my-2 px-2" errorClass="alert alert-danger" 
  infoClass="alert alert-info" />
```

```.java
FacesMessage errmsg = new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, null);
facesContext.addMessage(null, errmsg);
```
Bashのスクリプトをちょっとした手間でdry-runに対応したい

小ネタ。ちょっとしたBashスクリプトを書いている時によくやっています。


背景
---------

「Bashスクリプトを書いたけど、実行するとファイル削除されたりするから勇気がいる…」といったことがあります。ファイルを削除せず一旦mvにするなどして、やり直しがきくやり方を考えるとかもありますが、人生やり直しがきくことばかりでもありません。

そのため「スクリプトを実行したら何が起きるか？」を確認できるようにしたいことがあります。これをちょっとした手間で対応してみましょうという話です。

例
-----------

以下がちょっとした手間を含むスクリプトです。

``` bash:mysctipt.sh
#!/bin/bash

# myscript.sh

set -ue

# コマンドをDRYRUNに対応！
function run(){
  if [ "${DRYRUN:-}" == "" ]; then  # 変数 "DRYRUN" が定義されていない場合は本当に実行する
     "$@"
  else # 定義されている場合はコマンドを表示
     {
       echo -n "[DRYRUN]"
       printf ' "%s"' "$@"
       echo
     } >&2
  fi
}

# 気になるコマンドの前に "run" をつけよう！
run rm -rf ./* "space ok"

echo done
```

実行例

```bash
# 実行例
export DRYRUN=1
bash myscript.sh

# 実行例 （環境変数を汚したくない場合）
DRYRUN=1 bash myscript.sh

echo "実際に実行"
unset DRYRUN
bash myscript.sh
```

出力例
```
[DRYRUN] "rm" "-rf" "./myscript.sh" "./prog.sh" "space ok"
done
[DRYRUN] "rm" "-rf" "./myscript.sh" "./prog.sh" "space ok"
done
実際に実行
done
```

https://wandbox.org/permlink/XN5xD1hfnHooPb9I


環境変数DRYRUNを渡すとrmコマンドの部分はコンソール出力されるだけになります。

もちろん、実際にコマンドは実行しなくなるので、副作用がある前提のコマンドの実行には注意しましょう。

上記の例では環境変数がないときはコマンドを実行してしまいます。本当に危険な操作の場合はデフォルトはDRYRUNにしたいという事もあると思いますが、それはちょっと書き換えて対応してください。

関数名や変数名は自由に置き換えて使ってください。


解説
-----

解説することもないですが。

### Bashのパラメータ展開

`${DRYRUN:-}` がミソです。Bashは環境変数と変数を同じ記述で参照できます。しかし`set -u`が効いている場合は未定義な変数を参照することとなってしまいます。その場合`${変数名:-デフォルト値}`という[パラメータ展開](https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbBB)が使えます。これは`変数名`に対応する変数もしくは環境変数が未定義の場合、`デフォルト値`を返します。


### 環境変数の渡し方

Bashではコマンドを実行する前に `Key1=value1 Key2=value2 コマンド 引数...` というような形で実行することで、そのコマンドだけに環境変数を渡して実行することができます。`コマンド`はbashに限りません。コマンドには環境変数"Key1"と環境変数"Key2"が設定されます。環境変数が汚れないのでお勧めです。

Bashで実行中に環境変数を設定するには `export Key1=value1`という表記も使えますが、これは以降の操作時の環境変数にも影響します。環境変数を削除したい場合は`unset Key1`とします。`export Key1=`としてしまうと、空文字列のKey1が環境変数として定義されるので注意です。

また、スクリプトが複数に分かれていて入れ子構造のように呼び出していても環境変数で渡されていくので、便利です。

応用として `if [ "$DEBUG" != "" ] set -x` みたいなことをスクリプトの先頭でやっておくと簡易トレースができます。`bash -x myscript.sh`だとスクリプト内で`bash any.sh`とやられると`set -x`が途切れますが、先頭に書いておくと同じ理由で対応できます（どこかのBlogで見かけていいなと思って真似ていたのですが、出典を失念してしまった...）

あと引数をswitchでパースするスクリプトを見ますが、環境変数だとパースの必要がなく簡単です。

### `printf ' "%s"' "$@"` とは

手を抜いて `echo "$@"` でもいいのですが、この場合、引数の区切りがわかりにくくなるのでこういう指定にしています。上記の例だと `space ok` の引数が1引数か2引数か区別できなくなるので、それを区別できるようにしています。

printfコマンドはprintfっぽい挙動をしますが、引数が多すぎる場合、formatを繰り返し評価して連結します。今回の場合、format部分の書式は`%s`の1つだけなので、単純に引数の数だけformatが評価されます。例えば`printf "%s,%s" 1 2 3`とした場合、`1,23,`という出力になります。引数が不足している書式部分については、書式に基づいた処理になります。例えば`%s`は空になりますが、`%04d`だと"0000"のようになります。

### dry-runとはなにか

予行練習です。例えば「盛大に花火を打ち上げる」という作業を実際にやってしまうと取り返しがつかないコストが掛かります。なので **やったものとして** 作業を進めます。実際には行いませんが、この通しをするだけでも安心できるでしょう。

なので、dry-runをサポートするときは副作用がないようにするべきです（例えばファイルを作ったり消したりするような操作を全て今回のやり方でdry-runに対応するようにする）

実際は副作用がある操作を絡めてスクリプトにしたくなることもあるのでなかなか難しいとは思いますが…
DI

いつもなんとなくDIしてるので、基本をメモ


```C#
    public interface IGetWeather
    {
        public string GetWeather();
    }

    internal class GetSunny: IGetWeather
    {
        public string GetWeather()
        {
            return "晴れ";
        }
    }

    internal class GetRain : IGetWeather
    {
        public string GetWeather()
        {
            return "雨";
        }
    }
```


```C#
    internal class GetMessage
    {
        private IGetWeather getWeather;

        public GetMessage(IGetWeather getWeather)
        {
            this.getWeather = getWeather;
        }

        public void ShowMessage()
        {
            Console.WriteLine(getWeather.GetWeather());
        }
    }
```


```C#
    class Program
    {
        static void Main(string[] args)
        {
            var services = new ServiceCollection();
            services.AddTransient<IGetWeather, GetSunny>();
            services.AddTransient<GetMessage>();

            var provider = services.BuildServiceProvider();
            var message = provider.GetRequiredService<GetMessage>();
            message.ShowMessage();
        }
    }
```
2023/1/29主にITとかセキュリティの記事

正規の「リモート管理ソフト」が攻撃者のバックドアに - 米政府が警戒呼びかけ
https://www.security-next.com/143193

多数システムでランサム被害、復旧や事業継続に追われる - ならコープ
https://www.security-next.com/143034

委託先にサイバー攻撃、顧客などへ脅迫メール届く - 北関東マツダ
https://www.security-next.com/143040

狙われる「Telerik UI for ASP.NET AJAX」の既知脆弱性
https://www.security-next.com/143178

チェック・ポイント、2022年12月に最も活発だったマルウェアを発表　〜日本国内ではFormbookが首位、25％の組織に影響を与え2位以下を引き離す(1/27)
https://securityinsight.jp/news/13-inbrief/5304-230127-3

2022年度 第2回サイバーセキュリティセミナーを開催します（九州経済産業局）(2/10開催)
https://www.pref.nagasaki.jp/bunrui/shigoto-sangyo/sangyoshien/sisaku/keisansyo/594430.html

ＦＢＩ、逆ハッキング奏功　１７０億円ランサム阻止(1/27)
https://www.sankei.com/article/20230127-577G3QF4ZRNH3HRIPSJ7CUJQQY/

社員でサイバー防衛＝欠陥発見で報奨金、来年度導入―ＮＴＴ(1/26)
https://www.risktaisaku.com/articles/-/76291

「サイバー空間での日本」はハイリスクな場所―セキュアワークスが提言する「セキュリティ・アンラーニング」とは(1/27)
https://internet.watch.impress.co.jp/docs/news/1473521.html

米司法省、ランサムウェアグループ「Hive」の解体に成功(1/27)
https://japan.zdnet.com/article/35199197/

BINDにDoS引き起こす恐れある脆弱性、アップデートを(1/27)
https://news.mynavi.jp/techplus/article/20230127-2577086/

買い取ったMacBook、ロック解除できなければ破壊しかない模様。中古業者に打撃(1/27)
https://news.yahoo.co.jp/articles/f7b93884f0cc2ab97cf2276cf460dbfe5a290eb6?source=rss

pgAdmin 4 にディレクトリトラバーサルの脆弱性(1/27)
https://scan.netsecurity.ne.jp/article/2023/01/27/48833.html

2022年に「ノートン」がブロックしたサイバー攻撃は約7億件!? そして今年起こり得る犯罪の4つの手口(1/27)
https://internet.watch.impress.co.jp/docs/column/dlis/1472893.html

アメリカ内務省でも使われてしまった「単純なパスワード」が危険な理由(1/27)
https://ascii.jp/elem/000/004/121/4121712/?rss

調査報告: 量子に取り組むグローバル企業の71%が、2022年に100万ドル以上を量子コンピューティングへの取り組みに ～2021年から2.5倍以上の増加～(1/26)
https://news.nicovideo.jp/watch/nw12015495

アダストリア、自社ECサイト「ドットエスティ」を1月26日正午に再開 不正アクセスで8日間サイト休止(1/27)
https://news.mynavi.jp/techplus/article/20230127-2576926/

アルファロメオ初の電動車「トナーレ」、NFTで車両価値高める(1/27)
https://xtech.nikkei.com/atcl/nxt/column/18/01537/00666/

「データの宝庫」小売り、NRFで見えた活用の古くて新しい2大テーマとは(1/27)
https://xtech.nikkei.com/atcl/nxt/column/18/02328/012500007/
部分テンプレート

# 部分テンプレートとは
- 繰り返し使用するコードを取り出してひとつのファイルで管理できる仕組み

# 部分テンプレートの作成
- 部分テンプレートとして運用するファイル名の先頭に_(アンダースコア)をつけるだけ
```
_〇〇.html.erb
```
### 部分テンプレート内の記述について
- 部分テンプレート内では、インスタンス変数を使用するのは適切ではないためローカル変数で記述する。


# 使い方
```
# 基本の記述
<%= render [部分テンプレートファイルの指定], [ローカル変数]:[渡す値] %>
# 使用例
 <%= render partial: "ディレクトリ名/〇〇", locals: { post: @post } %>
# これで部分テンプレートのなかで、postのなかに＠postを格納できる
```
- renderメソッド
部分テンプレートを呼び出すメソッド

- partialオプション
renderメソッドで使用
オプションで部分テンプレート名を指定して、部分テンプレート呼び出せる。

- localsオプション
renderメソッドで使用
localsというオプションをつけることで、部分テンプレート内でその変数をつかえるようになる。
正規表現の否定先読み、OR条件

```
 /\A(?!.*(\.{2,}|\.{1,}@)).*\z/
```
文中に連続の.(ドット）または＠（アットマーク)前に一回以上の.(ドット）が来ると否定できるようになった。
以下の出典先を真似して書いてみた。

# OR条件
```ABC|DEF のように書くと、「文字列ABC、または文字列DEF」という OR条件 の意味になります```

# 出典
https://qiita.com/jnchito/items/6f0c885c1c4929092578#:~:text=ABC%7CDEF%20%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E6%9B%B8%E3%81%8F%E3%81%A8%E3%80%81%E3%80%8C%E6%96%87%E5%AD%97%E5%88%97ABC%E3%80%81%E3%81%BE%E3%81%9F%E3%81%AF%E6%96%87%E5%AD%97%E5%88%97DEF%E3%80%8D%E3%81%A8%E3%81%84%E3%81%86%20OR%E6%9D%A1%E4%BB%B6%20%E3%81%AE%E6%84%8F%E5%91%B3%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99

# 否定的先読み
パターンを否定する。
この場合は文中に含まれる```abc```が否定される
```
^(?!.*abc).*$
```
# 出典
https://uxmilk.jp/50674#:~:text=%E3%81%AB%E3%81%97%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82-,%E3%80%9C%E3%82%92%E5%90%AB%E3%81%BE%E3%81%AA%E3%81%84,%5E(%3F!.*abc).*%24,-%E3%80%9C%E3%81%BE%E3%81%9F%E3%81%AF%E3%80%9C%E3%82%92%E5%90%AB

# 感想
調べることに時間がかかったので記事にした。
正規表現はまだ全然慣れていない。
これで区切りがついた。
これが終わると次にいつ使うかわからない。
しかし勉強してよかった。
Jetpack composeでMaterial2とMaterial3を同時に使用すると色変わらなかった話

## 言いたいこと
Material2とMaterial3はちゃんと分けて使用したほうがいい。
と言うか、可能ならMaterial3にちゃっちゃと移行するべし。
(まだまだなところはあるから、めちゃくちゃ様子見しているが、、、）

## 起こったこと
`contentColor`の色が適応されないやんけ！！
|想定|実際|
|---|---|
|![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2064382/d149af49-cd97-19da-cbdf-e916df2b7fb5.png)|![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2064382/36cb55e8-10e1-6a0d-0f70-f7379180209a.png)|
|![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2064382/78859879-c833-e90c-8e1e-16239aac69e4.png)|![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2064382/26b489b8-a4a6-d2a7-396d-d7c0fa1f4cdf.png)|

## 状況
業務でJetpack composeを使用したUIの作成を行っているのですが、
TopAppBar周りでMaterial3を使用したく導入して実装していました。

:::note info 
バージョン
Jetpack compose bom : 2022.12.00
→ Material : 1.3.1
→ Material3 : 1.0.1
:::

起きた現象をシンプルに書くとこんな感じ

``` kotlin
@Composable
fun Sample(@DrawableRes iconId: Int) {
    // M3 Surface
    Surface(
        color = AppTheme.colors.backgroundPrimary,
        contentColor = AppTheme.colors.primary,
    ) {
        // M2 Icon
        Icon(
            painter = painterResource(id = iconId),
            contentDescription = null,
        )
    }
}
```

親レイアウトにMaterial3のコンポーネントを使用してtintの色を指定していたのですが、なぜかIconの色が変更されません。

## 原因
理由はおそらく**Material2とMaterial3の`LocalContentColor`は別物**っぽいから。

そもそもMaterial3では色やテーマの扱い方が変わっています。
[デザイントークン](https://m3.material.io/foundations/design-tokens/overview)というものが導入されて、役割やテーマの状況、Material Youなどによって色というものが変化するようになりました。
そのため`CompositionLocalProvider`に`contentColor`を渡しても適応されないようです。

## 対応
対応策としては使用するコンポーネントかスクリーンでMaterial2かMaterial3どちらかに統一するしかないかなと思っています。
上記のレベルくらいであればSurfaceの`contentColor`でColorをきちっと指定して親レイアウトが2でも3でもどちらでも大丈夫なように実装するのが無難かもしれない。

## 余談
おそらく互換性を持たせることはない気がしています。
Material3がStableになったとはいえ、まだまだ実験的なところが多いので様子見をしていますが、
早めにマイグレーションできるようにMaterial3の動向はチェックしておいた方が良さそうです。
Apache + PHP8の設定と動作確認 - Windows11

前提条件：
としてはApache + PHPは個別ごとインストールされている。
各インストール方法は以下を参照してください。

https://qiita.com/taidong5588/items/779928804a6f4eb98890

https://qiita.com/taidong5588/items/f250ab10e4122a04046a

 Apache を利用版VS16 x64 Thread Safeをインストールすること。
　WEBサーバーとして IIS を利用のPHP版はphp8apache2_4.dllは存在しない。
# Apacheでのhttpd.confの設定
「C:\Apache24\conf」フォルダにあるhttpd.confファイルをテキストエディタで編集します。以下のコードをhttpd.confファイルの末尾に追加します。
```php
PHPIniDir "c:/php"
LoadModule php_module c:/php/php8apache2_4.dll
AddType application/x-httpd-php .php
```


# Apache + PHPの設定と動作確認
Apacheの「C:\Apache24\htdocs」にphpinfo.phpというファイルを作成し、以下のように編集します。
```php
<?php
echo phpinfo();
?>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/8b212d62-a8b8-ae85-3d71-956acc62866d.png)

ブラウザを起動し、http://localhost/phpinfo.phpにアクセスします。

このようなPHPのバージョンや詳細情報が掲載されたページが表示されれば、成功です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/5ed1dc1c-a2df-6761-2512-1f60f5b4bbf5.png)
デメテルの法則をGoで確認する

### デメテルの法則 is 何
* ソフトウェア設計の一つのプラクティス
    *  英語では`Law of Demeter（LoD）` 。最小知識の原則とも。
*  「尋ねるな、命じろ（Don't ask,tell）」と言い換えることができる
*  部品を使う側は、使われる側の細かい事情を知らなくても使えるようにする、ということ

https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%A1%E3%83%86%E3%83%AB%E3%81%AE%E6%B3%95%E5%89%87

### デメテルの法則に反している例
* あえて使われる側（部品側）のコードは記載していません
* 使う側の気持ちになって処理を確認してみる
```go
package main

func main() {
    // ...省略

	// 勇者パーティーを生成する
	party := NewParty(members)
	if len(party.members) > 0 {
		// もしパーティーメンバーが一人以上いたら、画面表示用のメンバーを取得する
		memberForShow := party.members[0]
		// 上記で取得したメンバーを画面表示する
		showFirstMember(memberForShow)
	}
}

```

### 使う側が、使われる側の細かい事情を知った上で操作するのはしんどい
* メンバーが1人以上いたら、とか最初のメンバーを取得して関数に渡す、とか使う側があれこれ配慮しないといけない
* そういう配慮を忘れてしまったら（例えば1人以上のチェックをしなかったら）バグが発生するかもしれない
* なので、使う側は単純に「こうしろい！」と命令できるようにしたい。「これってできますか……？ できなかったらどうすればいいですか……？」といちいち聞かなくては使えないような部品は提供してはいけない。

```go
package main

func main() {
    // ...省略

	// 勇者パーティーを生成する
	party := NewParty(members)
    // パーティー最初のメンバーを画面表示する
    party.showFirstMember()
}
```
* バチクソシンプルになった
* 細かい処理や配慮は、使われる側の責務として実装させる
* ただ、上記のコードだと、エラー処理はどうすんの、ってことになる


```go
package main

func main() {
    // ...省略

	party,err := NewParty(members)
    if err != nil{
        // そもそも0人パーティーを作った時点でエラーを発生させる
        return err
    }

    if err = party.showFirstMember() ; err != nil{
        return err
    }
```

### デメテルの法則を適用させるときは、コンポーネントの責務を再確認するときでもある
* 構造体の状態が正しく保たれるか、メソッドが正常に実行できるか、これらを担保するのはコンポーネント（部品）側の責務である
* 使う側があれこれ面倒をみないといけない状況は、ドメイン知識が漏れていたり、コンポーネントの凝集度が低下していたりする可能性がある
* デメテルの法則に反しているコードは、部品を使う側で、if文やswitch文などの制御文が多く使われていたり、ドット繋ぎで構造体の中身へのアクセスが頻繁に行われていることが多い
* こういったコードは保守性を損なわせるので積極的にリファクタリングしていこう
Androidの全角/半角の正規表現には注意が必要

## 結論：Androidで半角/全角区別する正規表現は`[0-9]`や`[a-zA-Z0-9_]`を明示的に使用しよう
端的に言うと`\d`を使用しても全角数字もマッチ、`\w`は全角英数字もマッチするよ、というお話

## 起こったこと
先日、業務で「インプットからの文字列に、半角数字以外が含まれている場合はバリデーションエラーを表示する」というごくごく普通の要件を満たす正規表現を書いていました。
KMMでロジックを記載しテストコードもバッチリ通っているのに、いざAndroidで試そうと全角数字を入力してところバリデーションエラーが出ない！！という状況に至りました。

もしかして、Kotlin/Native → Kotlin/JVMでの不具合か？と思って
[Kolint online](https://pl.kotl.in/Q_Fa3S0Oc)で試したところ

``` kotlin
fun main() {
    println("全角 １ is ${isError("１")}")
    println("半角 1 is ${isError("1")}")
}

fun isError(value: String): String {
    val regex = Regex("""\D+""")
    
    if (value.contains(regex)) return "Error"
    
    return "OK"
}

// Kotlin
// 全角 １ is Error
// 半角 1 is OK

// Android
// 全角 １ is OK
// 半角 1 is OK
```

嘘やん、、、
なんでAndroidだけ違うの、、、
ちなみにiOSではKotlinと同じく想定通りに動きました。

## 解決
``` kotlin
fun main() {
    println("全角 １ is ${isError("１")}")
    println("半角 1 is ${isError("1")}")
}

fun isError(value: String): String {
    val regex = Regex("""[^0-9]+""")
    
    if (value.contains(regex)) return "Error"
    
    return "OK"
}

// Kotlinも Androidも
// 全角 １ is Error
// 半角 1 is OK
```
https://pl.kotl.in/LO0pzc8BG

冒頭にも書いたように明示的に文字クラスを使うとAndroidでも想定通りの結果になりました。

## 原因
結局のところあまり深く理解していないのですが

https://www.ecoop.net/memo/archives/regular-expression-problem-o-android-java.html

Unicodeの文字判定に依存するらしいです（小並感）
人に教えてもらうまで結構詰まってました。

メタ文字があるのに文字クラスを使用するとAndroid studioでめちゃくちゃ波線がでるけど、KDocに残してLintはsuppressしましょう！

## 余談
もともとInt型に変換できればええやろ！という実装がなされていたのですが、それだとそもそもKotlinで全角/半角の区別がないようです。

``` kotlin
fun main() {
    println("全角 １ is ${isError("１")}")
    println("半角 1 is ${isError("1")}")
}

fun isError(value: String): String {    
    if (value.toIntOrNull() == null) return "Error"
    
    return "OK"
}

// 全角 １ is OK
// 半角 1 is OK
```
草莽Erlang ── 40. lists:duplicate

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## lists:duplicate/2

[lists:duplicate/2](https://www.erlang.org/doc/man/lists.html#duplicate-2)は、リストを指定された回数コピーし、新しいリストを返します。

```erlang
> lists:duplicate(2, [1, 2, 3]).
[[1,2,3],[1,2,3]]

> lists:duplicate(3, [1, 2, 3]).
[[1,2,3],[1,2,3],[1,2,3]]

```

[listsモジュール](https://www.erlang.org/doc/man/lists.html)には他にもリスト処理のための関数がたくさんあります。

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1
No.5 折れ線グラフを追加する

# 折れ線グラフを追加
**1．ビルドから「折れ線グラフ」を選択
2．テーブルを展開し、積み上げ縦棒グラフで表示したい項目を選択する（今回は「月毎」の「売上」を確認する）**
X軸：月
Y軸：売上の合計
**3．表示されたビジュアルを確認する**
![作成1ezgif-4-c3fd7b6162.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/838c4195-708f-caec-c61d-f7be9b6ec20a.gif)


# 折れ線グラフの編集
**1．ビジュアルの書式設定を選択
2．詳細ラベルからオプションを選択。割合の表示箇所や内容を変更**
ex.)
マーカー・・・シェイプのサイズを大きくする、色を変更する
データラベル・・・月毎の売上を表示する
![編集ezgif-4-912566986c.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/3a9d1be4-ab91-ceb4-139b-e0ca3dba5af9.gif)


# 積み上げ縦棒グラフの利用シーン
・データの推移を確認するために利用
・面グラフも同じように推移を確認するために利用可能。こちらは視覚的に量を表したい時に利用
![スクリーンショット 2023-01-29 0.55.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/4ba46ca2-30d6-ca1d-201c-ac2709117656.png)

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
libnoiseをVisualStudioで使う

## 概要

libnoiseをVisualStudioで使おうとして詰まったのでメモ。

## 環境
- Windows11
- Microsoft Visual Studio Community 2019
Version 16.11.10

## 手順
※公式サイトからのものは古いためコンパイルが面倒。
　⇒以下のサイトを参考に、cmakeでx64コンパイルして使用

http://sssiii.seesaa.net/article/401018483.html

1. 以下からCmake対応のlibnoiseを持ってくる

https://github.com/qknight/libnoise/
    
2. Cmakeでコンパイル
    ※CmakeGUIを使用しています。
    1. Where is the source codeにCMakeLists.txtがあるフォルダを指定
    ![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325528/6363b175-4fea-19ce-c4e1-50de5f729713.png)
    1. libnoise-master以下にbuildフォルダを作成
    2. Where is the build the binariesは、上で作成したフォルダを指定
    3. Configureボタンを押下
    4. Generateを押下し、Visual Studioのバージョン等を設定し実行
    5. buildフォルダにslnファイルができるため、それを開きbuildする
3. libnoiseを使用したいVisualStudioのプロジェクトに.lib、.dll、headerを持ってくる
    1. プロジェクト以下にフォルダを作成し、必要なファイルを配置する。
    　以下は例
    ```cpp
    
    Project
      |-.sln
      |- x64
      |   |-Debug
      |      |-.exe
      |      |- noise.dll
      |-Venders
         |- libnoise
             |-bin
             |  |-noise.lib
             |- include
                |-noise
    
    ```
    
4. VisualStudioとlibnoiseをリンク
    1. VisualStudioにて、プロジェクトのプロパティを開く
    2. 構成プロパティ⇒VC＋＋ディレクトリ⇒全般⇒インクルードディレクトリにVenders/libnoise/includeのフォルダを追加
    3. ライブラリディレクトリにVenders/libnoise/binのフォルダを追加
    4. 構成プロパティ⇒リンカー⇒追加のライブラリディレクトリにVenders/libnoise/binのフォルダを追加
    5. 構成プロパティ⇒リンカー⇒入力⇒追加の依存ファイルにnoise.libを追加
    6. これで環境設定は終了

## 簡単なサンプルコードで動くか試してみる
公式チュートリアルのコードを拝借

https://libnoise.sourceforge.net/tutorials/tutorial2.html


```cpp
#include <iostream>
#include <noise/noise.h>

using namespace noise;

int main (int argc, char** argv)
{
  module::Perlin myModule;
  double value = myModule.GetValue (1.25, 0.75, 0.50);
  std::cout << value << std::endl;
  return 0;
}
```

以下の結果が出力されれば成功！

```cpp
0.686347
```
AIで簡単音声認識

こんにちは、すきにーです。

今日は音声認識AIのwhisperを使って簡単に文字起こしををする方法を書いていきます。

**①whisperとは**
whisperとは、OpenAIが開発した音声認識AIです。
教師あり学習で68万時間の音声データを学習しており、高い音声認識精度を持ちます。

その性能の高さからStableDiffusion,ChatGPTと並んで「2022年のAI3大事件」の一つに挙げているサイトもあるほどです。

**②音声認識の実装**
whisperで音声認識をするのはとても簡単です。

まず、whisperをインストールします。
```
!pip install git+https://github.com/openai/whisper.git
```
whisperをインポートし、音声認識を書き起こします。
今回はウェザーニュースさんの天気予報を書き起こしました。
https://twitter.com/wni_live/status/1619308182735826944?cxt=HHwWgMDR3c6N-PgsAAAA
```
import whisper
model = whisper.load_model("base")
file = "" #ファイルのパス
result = model.transcribe(file)
print(result["text"])
```
結果
```
明日の天気をお伝えしていきます。
日本海岸は後半で雪となりそうですね。
はい、今日も雪の入り合おかったんですけども、明日について少しエリアは狭まってきますけども、まだ雪続きそうですね。
はい、各地の振り方など見ていくといかがでしょうか。
はい、まず明日の気圧配置の方で見ていただきますと、風型の気圧配置がまだ残っております。
北海道に本海がなど初めの地増えたいといったようなことはありそうですけども、夜の気圧配置に見ると冬型は解消されております。
ですので明日については雪振り続くエリア、気圧配置的には少しわかりづらいんですけども、こちらに日本海上の風の動きに注目をしてみますと、ちょっと動きが複雑になっております。
地上付近の風の動きを見ていただきますと、日本海政府ではにしよりの風、また日本海北部門にしよりの風がになっておりますけども、中部のあたりでは少し広がれように風のぶつかり合いというのが、特に日本海西側で起こりやすくなっているということになっております。
このため明日なんですけども、雲の動きの予想で見ていただきますと、基本的には日本海上にある水上六のどんどん減っていくんですけども、先ほどの風のぶつかり合いのエラインに対応した雲の帯というのがずっと夜にかけて残る予想、特に保険方面、エニガタ方面など、これによって一時雨になったりしながら、もう強热化を繰り返して続くことになりそうです。
明日の全国の予想、マップの方で見ていただきましても、神奈川にい方などは行きの予想。
そして秋田から北のエリアでは、初め雪が降っていても基本的には回復計効と、ということになりそうですので、特に北陸から東北南部に日本海外にかけて、雪の量まだ明日の逃中も続くだろうというふうに見ていただければと思います。
はい、詳しいお天気はアプリペザーニュースでもご確認いただけます。
ぜひご活躍ください。

```

それなりに合ってますね。
インカムやイヤホンマイクで話した音声だともっと正確に聞き取れます。

今回は音声が2人だったので、話し手によってパート分けができれば良かったのですが、
まだその機能は無いようです。


バージョン
whisper: 1.0
No.4 集合縦棒グラフを追加する

# 集合縦棒グラフを追加
**1．ビルドから「集合縦棒グラフ」を選択
2．テーブルを展開し、集合縦棒グラフで表示したい項目を選択する（今回は「月毎」の「地域毎」の「売上」を確認する）**
X軸：月
Y軸：売上の合計
凡例：地域
![作成1_ezgif-4-a76db9dafc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/3ba73c39-3fe3-5e1e-5899-cb425153c775.gif)
**3．日付のデータ型は、年／四半期／月／日が追加されますが、これだと見辛いため、今回は年と月のみ表示します（四半期と日はチェックを外す）**
![作成2_ezgif-4-43d92cc519.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/86796ba1-8706-b13e-cba9-622a17825ff7.gif)



# 集合縦棒グラフの編集
**1．ビジュアルの書式設定を選択
2．詳細ラベルからオプションを選択。割合の表示箇所や内容を変更**
ex.)
X軸・・・文字を大きくする
Y軸・・・文字を大きくする
凡例・・・文字を大きくする
データラベル・・・売上の値を表示

![編集ezgif-4-1595c1d399.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/366d0909-177a-cdf1-5bac-5c62a71c2e22.gif)

文字を大きくしたので色々見えやすくなりました。
![スクリーンショット 2023-01-29 0.32.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/e8984cdc-5221-68b1-aa7f-8dfc155ada80.png)


# 集合縦棒グラフの利用シーン
・月毎に各支社や地域毎で比較するために利用
もし年毎に見た場合、このようなシンプルなグラフになるので細かくデータを見たい場合に集合グラフを使うイメージです。
![スクリーンショット 2023-01-29 0.38.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/e7ff3f40-5400-14ce-6a78-72c858ed491e.png)



こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
GAME言語インタプリタ in C 【GAMEC】

GAME言語インタプリタ in C

昔懐かしのGAME言語のインタプリタをCで書いてみました。
基本的なシステムコールしか使ってないので、Cの動くシステムだったら全て動作すると思います。

GAME言語は今は廃れてしまいましたが、1980年前後にマイコンで手軽に使える処理系として一世を風靡しました。当時は、僕もGAME言語を参考に独自のインタプリタ・コンパイラを作って遊んでいたものです。

このプログラムはまだエラーチェックなどが十分ではないです。一応制御構文などは全部動きます。

### コンパイル、インストール、実行
カレントディレクトリにgamec.cと、makefileを置き、makeとして下さい。
実行は、gamec [file.gm]として動かして下さい。
行末が0xa（LF)で終わるテキストを読み込みます。

makefile
```makefile
gamec: gamec.c
	cc -o gamec gamec.c
	sudo cp gamec /usr/bin/
```

### 履歴
・2023年1月31日 16ビット配列の取得の所にバグがあったので訂正。
・2023年2月1日　マイナーチェンジ＆名前をgamelinuxにする。
・2023年2月2日　バグ修正 ver 0.9
・2023年2月3日　getch()関数を内包 ver 0.9.1
・2023年2月4日　for文修正 ver 0.9.2
・2023年2月8日　for文の普通の言語モードで動作するのを　*FM 1に、GAME言語モードで動作するのを*FM 0にする。 ver 0.9.3
・2024年7月24日 数のサポートをushortからshortにする ver 1.0.0
・2024年8月24日 １文字入力をハードgetcharから、getcharにする。名前をgamecにする  ver 1.0.1
                
# 文法

・Jun Mizutani氏のGAME言語の文法を修正してアップします

```
<行番号>   1 〜 32767
<10進定数> -32768 〜 32767
<16進定数> $0000 〜 $FFFF
<文字定数> "文字"
<変数名>   A 〜 Z または冗長形(ABC等 先頭1文字が有効)

<2バイト配列> ::= 変数名 ( <式> )
                  変数の値 + 2 * 式の値 のアドレスの内容を値とする．

<1バイト配列> ::= 変数名 : <式> )
                  変数の値 + 式の値 のアドレスの内容を値とする．

<定数> ::= <10進定数> | <16進定数> | <文字定数>

<変数> ::= <変数名> | <1バイト配列> | <2バイト配列>

<式> ::= <項> | <項> <二項演算子> <項>

<項> ::= <定数> | <変数> | <配列> |（ <式> ）| <単項演算子> <項>　|  $  | ?
              $ は一文字入力、? は数値入力

<二項演算子> ::= + | - | * | / | = | <> | < | > | <= | >=
                比較演算 は 真:1, 偽:0の値を取る．

<単項演算子> ::= - | + | % | ' | #
                 + は絶対値, % は直前に実行した除算の余り,
                 ' は乱数, #は否定．
<行> ::= <行番号> スペース <文> [ 空白 <文> ] 改行
         | <行番号> スペース以外の文字 コメント 改行

<文>
    *AB              オプショナルコマンド　この場合はABというコマンド
    <変数>=<式>     変数への代入
    #=<式>            <式>の値の行番号の文にジャンプ(GOTO)
                      式の行番号がなければｓより大きい最初の行へジャンプ
    #=-1              プログラムの終了(END)
    !=<式>            <式>の値の行番号のサブルーチンへジャンプ(GOSUB)
    ]                 サブルーチンから戻る(RETURN)
    ;=<式>            式の値が真の場合は次の文に進み，
                      偽の場合は次の行を実行．
    @                 DO
    @=(式)            UNTIL
    変数=初期値,終値    FOR
    @=式              NEXT
    /                 改行出力
    "文字列"          文字列出力
    ?=<式>            <式>の結果を数値出力 左詰め
    ??=<式>           <式>の結果を数値出力 16進4桁
    ?$=<式>           <式>の結果の下位1バイトを数値出力 16進2桁
    ?(n)=<式>         <式>の値の数値出力 n桁で右詰め
    $=<式>            <式>の値の下位バイトを文字コードとする１文字を出力
    .=<式>            <式>の値の下位バイトの数だけ空白を出力
    '=<式>            <式>の値で乱数シードを設定

```

GAME言語についてはこのサイトが詳しいようです。

http://www43.tok2.com/home/cmpslv/Manual/GAME%20(J)(1979)(Ascii).pdf

GAME言語コンパイラ

https://qiita.com/fygar256/items/655bc44cc42f85c2f68f

# 本体 'gamec.c'

https://gist.github.com/fygar256/59eb051485cebd43db0e48ea3ac79ae5

# サンプルプログラム

test1

```test.gm
#!/usr/bin/gamelinux
10"***comment ***"
100 "line 100 running "  !=10000
110 "line 110 running "  !=10000
120 "line 120 running "  !=10000
130 "line 130 running "  !=10000
9990 "end" /// #=-1
10000 "sub " 
10010 A=1,10 ?=A " " @=a+1 /
11000 ]

```

# サンプルプログラム実行結果

```
line 100 running sub 1 2 3 4 5 6 7 8 9 10 
line 110 running sub 1 2 3 4 5 6 7 8 9 10 
line 120 running sub 1 2 3 4 5 6 7 8 9 10 
line 130 running sub 1 2 3 4 5 6 7 8 9 10 
end
```
No.3 100%積み上げ縦棒グラフを追加する

# 100%積み上げ縦棒グラフを追加
**1．ビルドから「100%積み上げ縦棒グラフ」を選択
2．テーブルを展開し、100%積み上げ縦棒グラフで表示したい項目を選択する（今回は「支社毎」の「売上」の「商品の内訳」を確認する）**
X軸：支社名
Y軸：売上の合計
凡例：商品
**3．表示されたビジュアルを確認する**
![作成ezgif-4-721d5b3c94.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/4f44718a-92ce-669c-fe7b-74d4a88a3dc1.gif)


# 積み上げ縦棒グラフの編集
**1．ビジュアルの書式設定を選択
2．詳細ラベルからオプションを選択。割合の表示箇所や内容を変更**
ex.)
データラベル・・・内訳の値を表示
**3．値が小さい場合は、文字を大きくする事も可能**
![編集ezgif-4-62336cda71.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/c1bc5c14-15bd-908f-82b8-7644e55dc8f8.gif)


・今回は各商品の割合が表示されています
![スクリーンショット 2023-01-29 0.05.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/5f960c61-b14d-562a-e537-b4ba346f62b0.png)


# 積み上げ縦棒グラフの利用シーン
・データの中身を比較するために利用（今回は支社毎の各商品の売上比率）
・100%積み上げ棒グラフにする事で、割合として見る事ができる
例えば、「なんで大阪梅田支店は他の支店と比べて**02．システム構築**と**06.リース**
の売上比率が高いねん。」（なんで関西弁やねん）というような形で、分析の切り口として使う事ができます。
![スクリーンショット 2023-01-29 0.06.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/6168b7f7-c4ed-aa49-0459-4faaf1cf8650.png)

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
DNSサーバーBINDについて

DNS（Domain Name Server）
ホスト名とIPアドレスを変換するシステム。

Linuxで標準的に使用されるDNSサーバは BIND。デーモン名は named
動作設定ファイルは /etc/named.conf 。

/etc/named.confにログ出力に関する設定が行われていない場合、BINDはsyslogにログを送信。syslogの出力するログファイルは設定ファイル（syslog.confなど）によって出力先を指定できますが、デフォルトではBINDから受け取ったログは
・/var/log/messages（RedHat系）
・/var/log/syslog（Debian系）
に出力。
Firebase App DistributionでFlutterで作成中のiOSのアプリをインストールした時のメモ

開発中のアプリを海外にいる人にインストールしてもらう必要があったのでメモ
ちょっとまだ、不明確な部分もある。

# 必要な作業
- ExportOptions.plist　の作成
    - 作成場所は　[プロジェクトディレクトリ]/build/ios
    - 以下のような感じでOK
    - 多分、他にも作る方法はあると思うが、調査不足
    - 手動で作らないほうがいいのかもしれない？

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>compileBitcode</key>
    <true/>
    <key>destination</key>
    <string>export</string>
    <key>method</key>
    <string>ad-hoc</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>xxxx.ipa</key>
        <string>flutteripa</string>
    </dict>
    <key>teamID</key>
    <string>[teamID]</string>
    <key>thinning</key>
    <string>&lt;none&gt;</string>
</dict>
</plist>
```


- ipaファイルの作成
    - コマンドは flutter build ipa --release --export-options-plist="ios/ExportOptions.plist" 
    - flutter build ipa だけだとアーカイブしか行われない
    - pod initやpod updateなどしないといけない場合もある
    - ipaファイルは [プロジェクトディレクトリ]/build/ios/ipa に生成される
    - ダメな場合はxcodeでやったほうが良さそう。
- FirebaseにiOSプロジェクトの作成
- App Distributionにipaファイルを登録
    - これは作ったIPAファイルをドラッグ&ドロップで登録するだけなので簡単。
- インストールしたい人を招待
    - Googleアカウントが必要
- 招待された人が登録するとUUIDが通知される
- UUIDを使って、プロビジョニングファイルを更新してビルド
   - これめんどい
- 再度配布

# 気になった点
- デバッグで使用していたデバイス（Macにつなげてデバッグしていたデバイス）はUUIDをプロビジョニングファイルに登録する作業を行うことなくできた。

# 気になったエラー

## Could not build the precompiled application for the device. Error (Xcode): Signing for "gRPC-C++-gRPCCertificates-Cpp" requires a development team. Select a development team in the Signing & Capabilities editor.

```
Could not build the precompiled application for the device.
Error (Xcode): Signing for "gRPC-C++-gRPCCertificates-Cpp" requires a development team. Select a development team in the Signing & Capabilities editor.
/Users/ozawatakayuki/AndroidStudioProjects/flyfishsamples/ios/Pods/Pods.xcodeproj
```

これは　gRPC-C++-gRPCCertificates-Cpp　の　TeamID　を設定して回避
調べてみると、Xcode14で発生する問題の模様。
対応方法調べないと。


## Failure Reason: failed to get the task for process XXXXX

プロビジョニングファイルを設定した後に実行したらタイトルのようなエラーがターミナルに表示され、iPhone側は真っ白な状態に。

以下のリンクの通りやってもダメだった
[【Xcode/Swift】実機でビルドすると、Could not launch “アプリ名” process launch failed: failed to get the task for process XXXというポップアップが表示される](https://ios-docs.dev/process-launch-failed/)

Product->Schema->Edit SchemaでBuild ConfigurationをReleaseに変更して解決した。


# 参考にした記事

- [flutter build ipaコマンドを使ってみた](https://takamii.hatenablog.com/entry/2021/07/02/151453)
- [【Flutter】エラーとの闘い](https://zenn.dev/sho5/scraps/bdb32f47ed8cc9)
- [[Development Team ID] プロパティ](http://wiki.genexus.jp/hwiki.aspx?%5BDevelopment+Team+ID%5D+%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3)
CreateReactAppでReact 18によるエラー対処

React学習してたらコンソールログにずっと出ているエラー分を調べてみたら、意外とつまづきそうな内容だったのでメモメモ。

![Screenshot 2023-01-28 at 23.41.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1935269/c98a20a5-9773-fada-a4e8-47d31d97fa37.png)

## 概要
Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead.Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot

***ReactDOM.render は、React 18 でサポートされなくなりました。代わりにcreateRootを使用してください。新しい API に切り替えるまで、アプリは React 17 を実行しているかのように動作します。詳細はこちら: https://reactjs.org/link/switch-to-createroot***

CreateReactAppで自動生成されるコードがReact 18に対応していないために表示されているWarningだそうです。

## 対処方法
対処方法は簡単でした。以下のコードに書き換えるのみです。
```src/index.js
import React from 'react';
- import ReactDOM from "react-dom";
+ import { createRoot } from 'react-dom/client';
import { App } from './App';

- ReactDOM.render(<App />, document.getElementById("root"));
+ const container = document.getElementById('root');
+ const root = createRoot(container);
+ root.render(<App />);

```

## 参考サイト
https://zenn.dev/kohski/articles/create-react-app-error-v18

https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html#updates-to-client-rendering-apis

## 最後に
一つ一つ覚えることが積み重なっていますが、まだまだ覚えることが多いのでReactです！これからも記事にしてアプトプット増やしていこうと思います！
No.2 積み上げ縦棒グラフを追加する

# 積み上げ縦棒グラフを追加
**1．ビルドから「積み上げ縦棒グラフ」を選択
2．テーブルを展開し、積み上げ縦棒グラフで表示したい項目を選択する（今回は「支社毎」の「売上」の「商品の内訳」を確認する）**
X軸：支社名
Y軸：売上の合計
凡例：商品
**3．表示されたビジュアルを確認する**
![作成ezgif-4-e84cd48b4b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/aa0df8d2-3268-bd89-a256-eadae9581073.gif)


# 積み上げ縦棒グラフの編集
**1．ビジュアルの書式設定を選択
2．詳細ラベルからオプションを選択。割合の表示箇所や内容を変更**
ex.)
データラベル・・・内訳の値を表示
合計ラベル・・・支社毎に売上の合計額を表示
**3．値が小さい場合は、文字を大きくする事も可能**
![書式ezgif-4-1004180511.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/c6b83f76-64d1-96ae-7fc3-2b5d004e483b.gif)

・合計ラベルとデータラベルの拡大図
![スクリーンショット 2023-01-28 23.47.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/2d03b7f5-769d-d253-4314-cbdc2326889d.png)


# 積み上げ縦棒グラフの利用シーン
・データの中身を比較するために利用（今回は支社毎の売上）
・積み上げを利用する事で、売上の内訳も同時に見る事ができる
・年毎にどの製品が売れているかなどを可視化できる

なお、このグラフに限らずですが、グラフ上にマウスオーバーすると値が確認できます。
![スクリーンショット 2023-01-28 23.45.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2943951/c6be7d8c-827e-ada4-8576-25ffd5c736d1.png)

こちらのセッションは以上です。
[→ Power BI サービス練習帳に戻る](https://qiita.com/shinyasasaki/items/391d50c2508794e8fcfd)
【Linux】特定の文字列を含む行の番号を取得する方法

## 取得方法

`sed`コマンドを使用して以下のように実行することで行番号のみを取得できます。  

```terminal
sed -n '/検索する文字列/=' sample.txt
```

以下のような内容で`sample.txt`を作成します。  

```txt:sample.txt
12345
あいうえお
12345
あいうえお
12345
あいうえお
12345
あいうえお
12345
あいうえお
```

`1`が含まれる行の行番号を取得するために以下のコマンドを実行します。  

```terminal
$ sed -n '/1/=' sample.txt
1
3
5
7
9
```

上記のように`1`が含まれる行番号のみを取得できました。
【Django】逆参照してCountとる時に条件（filter）を指定したい時

めちゃくちゃググったんですけどなかなか答えにたどり着けなかったので残しておきます。

## やりたきこと

そのタグが設定されている**公開済み**の記事の数をリストでほしかったんです。

### ほしかった結果
```
[
    {
        "id": 2,
        "name": "ウマ娘 プリティーダービー",
        "post_count": 3
    },
    {
        "id": 6,
        "name": "オーバーウォッチ",
        "post_count": 1
    },
    {
        "id": 3,
        "name": "NIKKE",
        "post_count": 1
    },
    {
        "id": 8,
        "name": "ビートマニア",
        "post_count": 0
    },

```


### ここからは実装の内容

記事モデル（post）と、タグモデル（tag）がありまして、記事モデルのほうからManytoManyでリレーション貼ってる感じです。

```python

class Tag(models.Model):
    name = models.CharField(max_length=40)


class Post(models.Model):
    class Statuses(models.IntegerChoices):
        PUBLISHED = 1
        DRAFT = 2
        PRIVATE = 3
        DELETED = 4

    user = models.ForeignKey(Profile, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    content = models.TextField()
    status = models.IntegerField(choices=Statuses.choices)
    tags = models.ManyToManyField(Tag, blank=False)
```

こんな感じです。

で、最初はこう書きました。

```python
Tag.objects.filter(post__status=1).annotate(post_count=Count('post'))
```

一瞬いけたと思ったんですよ。正直にこれにたどり着くまでにも時間かかってたので勝った気でいました。
が、だめでした。
テストコード走らせて気づいたんですけどこれだと、**タグがあっても、記事が存在しないと、タグ自体が返ってこない**んですよね。

annotateする前に、filterで絞っちゃってるから「まあそうか」って感じなんですけど。
テストコードに救われましたよね。みんなテストコード書きましょう。


## じゃあどうしたか

```python
from django.db.models import Q
Tag.objects.annotate(post_count=Count('post', filter=Q(post__status=1)))
```

Countクラスにfilterを追加することでいけました。

## 以下蛇足

これなかなか答えにたどり着けなかったんですよね。
https://y0m0r.hateblo.jp/entry/20120601/1338552629
こちらの記事でも同じことやろうとして、同じ問題にぶつかってるんですけどこちらはextraを使ってなんとかしたようですが、僕はどうしても諦められなかったんですよね。（こちらの記事は2012年に書かれたものなので当時はこれしか方法がなかったのかもしれません）

で、最終的にどうしたかというと、Countのクラスの中身を見てみたんです。

```django.db.models.aggregates.py
class Count(Aggregate):
    function = "COUNT"
    name = "Count"
    output_field = IntegerField()
    allow_distinct = True
    empty_result_set_value = 0

    def __init__(self, expression, filter=None, **extra):
        if expression == "*":
            expression = Star()
        if isinstance(expression, Star) and filter is not None:
            raise ValueError("Star cannot be used with filter. Please specify a field.")
        super().__init__(expression, filter=filter, **extra)

```

あるじゃん！！ `filter` !!
つまりできるはずなんです。
で、色々いじってみたら、上記にも書いてますけど、

```python
from django.db.models import Q
Tag.objects.annotate(post_count=Count('post', filter=Q(post__status=1)))
```

でいけましたとさ。

ドキュメントはこちら
https://docs.djangoproject.com/en/4.1/topics/db/aggregation/
【WinUI3】VS2022セットアップ

インストール ダイアログ ボックスの [ワークロード] タブで、必要に応じて選択します。

Windows App SDK を使用した C# アプリの開発の場合は、[.NET デスクトップ開発] を選びます。
次に、インストール ダイアログ ボックスの [インストールの詳細] ウィンドウで、[Windows App SDK C# テンプレート] (一覧の下部にあります) を選択します。
Windows App SDK を使用した C++ アプリの開発の場合は、[C++ によるデスクトップ開発] を選びます
次に、インストール ダイアログ ボックスの [インストールの詳細] ウィンドウで、[Windows App SDK C++ テンプレート] (一覧の下部にあります) を選択します。
Rustで関数テーブル（配列）を作って呼び出してみる

# はじめに
- 似たような関数で別の処理を連続的にさせたい
- 同じ引数を取るけど、全く別の実装を連続でやらせたい
- 同じ引数を取るけど、特定条件のときは別の関数を呼び出したい

みたいなことって有ると思います。

例えばこういうやつ。

```Rust
fn push_a_key() {
    // Aが押されたときの処理
}
fn push_b_key() {
    // Bが押されたときの処理
}
fn release_a_key() {
    // Aが離されたときの処理
}
fn release_b_key() {
    // Bが離されたときの処理
}
enum PushState {
    Push,
    Release,
}
fn get_key_input()->(char,PushState){
    ('A',PushState::Push)
}
fn main() {
    // A=0x41,B=0x42...のAsciiコードと押下状態のタプルが返却されるような仕様とする
    loop{
        match get_key_input() {
            ('A', PushState::Push) => push_a_key(),
            ('A', PushState::Release) => push_a_key(),
            ('B', PushState::Push) => push_b_key(),
            ('B', PushState::Release) => push_b_key(),
            _=>{}
        }
    }
}
```

のような時、分岐が邪魔ですね。
これはクソコードと言っても差し支えないです。
場合によってはいい気もするはするんですが、何個も何個も同じ処理を分岐で処理するのはイケてない気がします。

そこで、押されたキーコードにしたがって関数テーブルを直接指定出来たら嬉しいと思いませんか？
コードもスッキリしそうだなということでやっていきます。

``` Rust
#[derive(Clone)]
enum PushState {
    Push,
    Release,
}
fn get_key_input(i:usize) -> (char, PushState) {
    [('A', PushState::Push),('B',PushState::Release)][i].clone()
}
fn main() {
    let kh = init_handler();
    // A=0x41,B=0x42...のAsciiコードと押下状態のタプルが返却されるような仕様とする(範囲は0x20～0x7Fまで)
    for i in 0..2{
        let (key,state)=get_key_input(i);
        kh[key as usize](key,state);
    }
}

fn init_handler()->Vec<Box<dyn Fn(char,PushState)>>{
    let mut handler:Vec<Box<dyn Fn(char,PushState)>>=Vec::new();
    // このあたりの数値は適当
    for i in 0..255 {
        handler.push(Box::new(move |_,_| {}));
    }
    handler['A' as usize] = {Box::new(|key,state|{
        let h: Vec<Box<dyn Fn()>> = vec![
            Box::new(move || {println!("Aが押されたよー");}),
            Box::new(move || {println!("Aが離されたよー");}),
        ];
        h[state as usize]()
    })};
    handler['B' as usize] = {Box::new(|key,state|{
        let h: Vec<Box<dyn Fn()>> = vec![
            Box::new(move || {println!("Bが押されたよー");}),
            Box::new(move || {println!("Bが離されたよー");}),
        ];
        h[state as usize]()
    })};
    handler
}
```
実際に動かせます。どうぞ。

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=66cdb854ce759742b445f646b97a04ff

# 注意点
これは主にクロージャの注意点です。

- Boxで囲わないと駄目（Sizedでなければならない。要はポインタでないといけません。）
- 型宣言をちゃんと書く（手を抜こうと型推論に任せないでください。Rustちゃんは、おこです。）

# おわりに
ほら、なんていうかループ内にif文を書くって大分見通し悪いじゃないですか？
関数の中に沢山クロージャの処理が有るのが気に食わなければ、別のやり方でやっても良さそう。


というわけで今日は終わりっす。
Vitestで簡単テスト導入

# はじめに

Vitestは、Viteを利用した高速な単体テストフレームワークです。
VitestはほとんどのJest APIおよびエコシステム、ライブラリとの互換性を提供されているため
これまでJestを使っていた場合は特に違和感なく移行可能だと思います。
今回はVitestの導入について簡単に解説して行きます。
前提としてViteの設定は完了しているものとします。

# 環境構築
## インストール

> npm install -D vitest

その他テストに必要なライブラリもインストールします。
examplesからテスト環境に合ったものを参考にすると対応しやすいと思います。

[Vitest examples](https://github.com/vitest-dev/vitest/tree/main/examples "Vitest examples")

## config設定

vite.config.tsに追記します。
Viteの設定と統合されているのでセットアップが非常に簡単にできます。

```typescript
/// <reference types="vitest" />
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  test: {
    globals: true,
    environment: 'jsdom',
    setupFiles: './vitest.setup.ts',
  },
})
```

> globals: true

JestのようにAPIをグローバルに使用する設定

> environment: 'jsdom'

テスト環境を指定します。
ブラウザで表示するアプリケーションの場合は、

jsdomまたはhappy-domを指定します。

> setupFiles: './vitest.setup.ts'

セットアップファイルへのパスを指定します。
各テストファイルの前に実行されます。

[Configuring Vitest](https://vitest.dev/config/ "Configuring Vitest")
[Triple-Slash Directives](https://www.typescriptlang.org/docs/handbook/triple-slash-directives.html#-reference-types- "Triple-Slash Directives")

## tsconfig.json

TypeScriptをグローバルAPIで動作させるための設定です

```typescript
// tsconfig.json
{
  "compilerOptions": {
    "types": ["vitest/globals"]
  }
}
```

## vitest.setup.ts

`vite.config.ts`の`setupFiles`に設定したファイルに共通処理を記載します。
テスト内容によって記載する内容は変わってきます。
下記の例では依存ライブラリのimport、グローバル変数、
JSDOMに実装されていないメソッドのモックなどの設定をまとめて行っています。

```typescript
import '@testing-library/jest-dom'
import ResizeObserver from 'resize-observer-polyfill'

global.ResizeObserver = ResizeObserver
Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: vi.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    onchange: null,
    addListener: vi.fn(),
    removeListener: vi.fn(),
    addEventListener: vi.fn(),
    removeEventListener: vi.fn(),
    dispatchEvent: vi.fn(),
  })),
})
```

[JSDOMに実装されていないメソッドのモック](https://jestjs.io/ja/docs/26.x/manual-mocks#jsdom-%E3%81%AB%E5%AE%9F%E8%A3%85%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%AA%E3%81%84%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E3%83%A2%E3%83%83%E3%82%AF "JSDOMに実装されていないメソッドのモック")

# テスト実行

```typescript
npx vitest
```
vitestコマンドはオプションなしの場合watchモードで動作します。
process.env.CI=trueだとrunモード（watchモード無効）でテスト開始します。
CI環境がCircleCIやGithub Actionsの場合はCI=trueがデフォルトになっているので

package.jsonに

> "test": "vitest"

と書いておけば`npm run test`で環境ごとにうまく動作してくれます

# Vitest UI

ブラウザで詳細なテスト結果を見たいときは

> npm i -D @vitest/ui

をインストール

> vitest --ui

を実行することでブラウザが立ち上がって結果が表示されます。

# まとめ

実行速度が速く、設定も簡単なので
Vite導入済みの環境で単体テストを行う際は有力な選択肢になりそうです。
テストに便利な機能も色々あるので今後もVitestの動向を追って行こうと思っています。
【Swift】許諾ダイアログの言語について(備忘録)

・許諾ダイアログの言語についてほぼ自分用に備忘録を。

## 今回書いたきっかけ
一部の許諾ダイアログで「シミュレータ」と「実機」での相違に気がついた。

## 通知許可ダイアログで調査
### 1. シミュレータ
言語を「日本語」にしても、表示される言語は「英語」だった。

### 2. 実機
言語を「日本語」にしたら、表示される言語は「日本語」だった。

## 結論
まともに開発したいならやっぱり実機だろ～～～～～

## 最後に
iOSアプリ開発をしています。
主にSwiftですが、最近は熱が入ってきてFlutterも🦾
色々やってます。もし良かったら見てってください。

https://sogablog.net/
自作キーボード　QMKでctrl-HをBackSpaceにする

最近はキーボードのキーマップを変えることに凝っています。これまではHHKBをつかっていたのですが、気分を変えて自作キーボードを入手しました。

[QMK Firmware](https://github.com/qmk/qmk_firmware)をProMicro（マイコン）に書き込むタイプの自作キーボードなら、比較的簡単にキーマップを変えられます。
キー数を減らすにはレイヤーをどう設計するか。タップダンス（連打）をどこに取り入れるか。タップとホールドの調整はどうすると違和感が少ないかなど、日々試行錯誤しながら、キーマップ沼にどっぷり浸かっています。

さて今回はQMKでctrl-HをBackSpaceキーに変える簡単な方法を共有します。ブラウザでの文字入力時に履歴タブが開いて萎える方必見です。

[QMKのオーバーライド機能](https://github.com/qmk/qmk_firmware/blob/master/docs/feature_key_overrides.md)を使用します。GitHubの説明の通りですが、まずrules.mkに以下の記述を追加します。

```
KEY_OVERRIDE_ENABLE = yes
```

そして、Simple Example を参考にして、keymap.cに以下の記述を追加します。

```cpp
const key_override_t backspace_key_override = ko_make_basic(MOD_MASK_CTRL, KC_H, KC_BSPC);

// This globally defines all key overrides to be used
const key_override_t **key_overrides = (const key_override_t *[]){
	&backspace_key_override,
	NULL // Null terminate the array of overrides!
};
```

追加のコードはこれだけです。これをコンパイルしてマイコンに焼くと、履歴タブとはおさらばです。
.theia/launch.jsonとphp

https://shell.cloud.google.com でF5でデバッグできます

```json:.theia/launch.json
{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  "version": "0.2.0",
  "configurations": [
    {
      "type": "php",
      "request": "launch",
      "name": "Launch Program",
      "program": "${file}"
    }
  ]
}
```
VS Codeのデバックコンソールへの出力表示方法

友人がPythonを勉強用に参考書を購入したのだがよくあるprint"halo"が上手くいかないと呼ばれたので個人用にログとして残す

デバックなし実行をし確認するとこのような表記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2712564/4d2b14c5-0c92-b388-8bf0-a4bfc8092a38.png)

確かにデバックコンソールには何も表示されていないがターミナルを見る限りコードは問題なく動作している

調べてみると本の発行時とは仕様変更があったようだ
https://github.com/microsoft/ptvsd/issues/2036

launch.jsonを確認しようとするがそもそも作成がされていなかったので先ずは作成して確認する
方法に関してはこちらの方が詳細について記載してくれている
https://amateur-engineer-blog.com/vscode-launchjson/

  "redirectOutput": trueを追加し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2712564/2a06aec0-dec3-d3a2-5a0e-1f7e125fe081.png)
実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2712564/bb955114-2da9-65b7-db69-51b533cc2d08.png)

個人的には実行時にターミナルに自動で切り替わりが発生するのでデバックコンソールは別枠表示にしていた方が良さそうだ
Apache 2.4 のダウンロードとインストール - Windows11

Apache 2.4 をWindows上で動かすには、「Microsoft Visual C++ 2015 再頒布可能パッケージ」が必要です。まずはこちらをインストールしましょう。
 Microsoft Visual C++ 2015 再頒布可能パッケージのインストール
次の URL にアクセスし、インストーラをダウンロードしましょう。
https://www.microsoft.com/ja-jp/download/

# Apacheのダウンロードとインストール
Apacheをダウンロードするために「Apache Lounge」にアクセスします。

https://www.apachelounge.com/download/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/0cea68d3-5a54-2f7d-cd5c-b779538149cc.png)
ダウンロードしますしたzipファイルを展開します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/a03a0de3-4d55-77ef-fd6a-53e9c66f09d3.png)
展開した中にあるフォルダ（Apache24）をローカルドライブの直下に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/8462873f-73c7-556d-3472-a2217a51d33f.png)

実行ファイル（httpd.exe）を実行し、Apache24をサービスへインストールします。
```
C:\Apache24\bin\httpd.exe -k install
```
アクセスを許可する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/9396557f-720b-039f-3cb4-5ee5e6976e7e.png)

「ApacheMonitor」を起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/4c1465d9-44ef-44d5-b035-ab2c9b189809.png)
赤い羽根の「ApacheMonitor」にマウスカーソルを合わせ右クリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/31fab3b3-236e-e084-7a2e-834d1f4e7a95.png)
「Open Apache Monitor」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/02de69d8-4aa6-c17e-1a4a-e7c4918e95e3.png)
Open Apache Monitor」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/49d9597a-f1d3-de10-78a0-684a7194fc31.png)
「Apache Service Monitor」が起動するので、「Start」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/8b28d783-034e-47fd-29ec-10a387cfa4e4.png)
起動しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/9e99596d-2351-8f5c-0929-4ae9ca37ba88.png)
ブラウザを起動し、http://localhost/にアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592268/2c590d45-49de-f63b-20e3-ccf9b64d2103.png)
これでApacheの動作確認は完了です。
短歌を発表する人向けwebアプリ【縦書き画像メーカー】を作成しました。



<h2>はじめに</h2>

縦書き画像メーカーというアプリを作成して公開しました。
作成した理由や、使用した技術等記載していこうと思います。

https://make-textcard.netlify.app/



<h2>サービス概要</h2>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692485/d6b1621d-0c3b-252d-2bc9-0e6da87ad22d.png)

このように縦書き・複数行の文章を出力することができます。
Twitter等で短歌を発表する際に利用されることを想定しています。
フォントが複数選択できるため、好きな字体で文章を発表することができます。

↓想定利用例

https://twitter.com/akaiakaikinomi/status/1619327423358853122?s=20&t=3kcTJ7XauStiFry3xPTIwA

<h2>苦労したところ①</h2>

https://monthly-card.naichilab.com/

[ないち](https://twitter.com/naichilab)さんが公開されている上記アプリを参照。
上記アプリでは[html2canvas](https://html2canvas.hertzen.com/)という任意のhtml要素をcanvasに変換できるライブラリを使用している。
これを使って実装しようとしたところ、html2canvasは縦書きに対応していなかった……。
そのため、canvas要素をhtmlに直書きする方法を取ることに。

<h2>苦労したところ②</h2>
canvas要素に縦書きテキストを直書きしようとすると、こちらも縦書き非対応。<br>
そのため、一旦横書きテキストとして出力し、それを一文字分ずつ切り取って下にずらすという方法で描画することに。

（例）
ラーメン
↓
ラ
ー
メ
ン

参考にしたソースコード
https://codepen.io/phi_jp/pen/negKRO

<h2>苦労したところ③</h2>
上記例で見たように、単純に横書きテキストを一文字分ずつ下にずらすと、「ー」のように縦書き文字にならない項目が出てくる。<br>
他にも「。」の場合は、横書きのときは左下、縦書きのときは右上に位置するため、各記号それぞれで回転・移動処理を実装した。

<h2>感想</h2>
初めてwebアプリを作成して楽しかった。<br>
友人がたくさん遊んでくれて、励みになった。<br>
アプリの公開にはnetlifyを使用したが、Githubの連携や公開までの流れがスムーズで感動した。<br>

**少なくとも自分は使う**アプリが作れると、モチベーションも上がるしよいことがわかった。これからも何か作って公開してみたい。
Ruby 引数

# 引数とは
メソッドに渡すことができる値のこと。

# 実引数と仮引数
```ruby
def メソッド名(仮引数)
  # 処理
end

# メソッドの呼び出し
メソッド名(実引数)
```
メソッドを定義したときに（）内に記述しておき、処理に利用するときは***仮引数***。
メソッドを呼ぶときに（）内に渡す値を記述するのが***実引数***があります。

```ruby
def メソッド名(第一引数, 第二引数)
  # 処理
end

メソッド名(第一引数, 第二引数)
```
引数は複数利用されることがあります。<br>
そんなときは、（）内、左から順に第一引数、第二引数、第三引数...と呼びます。

例
```ruby
def get_weather_forecast(weather)
  puts "明日の天気は#{weather}です"
end

get_weather_forecast("晴れ")
```
<br>

```
# ターミナル出力
明日の天気は晴れです
```

<br>
- この例の場合、実引数="晴れ"、仮引数=weatherですね。<br>
- 明日の天気は〇〇です。の、〇〇は、任意の文字列を表示したいため、引数を使います。<br>
- 〇〇には、メソッドの呼び出し元の引数に渡した文字列が表示されます。<br>
- 文字列を出力するために、get_weather_forecastメソッドを定義します。<br>
- 引数で渡した文字列を表示させた値です。<br>
連想配列もどき（POSIX シェル）

こんにちは。
POSIX シェルで連想配列もどきを作りました。

* ただし関数ベタ書きで（下記ソース内の関数```dict_f```）、変数型（dictionary型、key-value型[^1]）を作ったわけではありません。

[^1]: POSIX シェルは元来このような型を持ちません（独自拡張を除く）

```console
$ dash dict.sh a
alpha
$ dash dict.sh
upsilon
$ dash dict.sh -h
  imitation: dictionary = {'a': "alpha", 'b': "beta", 'c': "gamma", 'default': "upsilon"}
$
```


```dict.sh
#!/bin/sh

USAGE=$(cat << EOS
  imitation: dictionary = {'a': "alpha", 'b': "beta", 'c': "gamma", 'default': "upsilon"}
EOS
)

dict_f() {
  key=$1
  case "$key" in
    '-h' ) echo "$USAGE"; exit;;
    'a' ) value="alpha";;
    'b' ) value="beta";;
    'c' ) value="gamma";;
    * )   value="upsilon";;  # default
  esac
  echo "$value"
}

dict_f "$1"
exit
```