OmniAICreator/Qiita-1.07M huggingface dataset:
若手エンジニア向け：ストックとフローの使い分け

コロナになって3年目、リモートワークもなれてきた頃です。皆さん、会社単位で、プロジェクト単位で、部署単位で、色々と工夫されてると思います。
リモートワークで最も重要なのが、**コミュニケーションツール**です。
この**コミュニケーションツール**の使い方で、特に若手エンジニアに向けたアドバイスです。

# ストック型のコミュニケーションツール
**ストック型**というのは、stock溜まっていく形のコミュニケーションツールを指します。
例えば、メール等、相手から送信の都度メールボックスにメールが届きます。これはメールという単位でメールボックスに溜まっていく方式になってるので、3日前のメールと今日のメールは、別々にメールボックスに存在します。つまり、ドンドンと溜まっていくコミュニケーションツールです。
メール以外にもチケット管理のツール、JIRA、redmineとかのツールもチケット単位になってるのと、チケットの更新の都度メールが送信されていて、ドンドンと溜まっていくコミュニケーションツールと言えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/e36fd95b-2573-10ba-e954-9ce4b81a6cd8.png)

# フロー型のコミュニケーションツール
**フロー型**というのは、flow流れていく形のコミュニケーションツールを指します。
例えば、slack,チャットワーク、メッセンジャー、line等です。メッセージがドンドンと流れていく形になってるので、スピード感あるし、軽いメッセージのやり取りには、最適です。複数人でのメッセージも最適で、他の人のやり取りを眺めながら自分の意見を差し込んだり、やり取りの状況を確認したり出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/26a06ada-0ab9-a921-86cf-24cf5e208e65.png)

# フロー型コミュニケーションツールの間違った使い方
昨今の仕事の殆どが、フロー型のツールに以降してきてます。社内だけでなく、社外とのやり取りもフロー型のツールに移行してきています。プロジェクトの中の特定の**連続性のあるトピック**についてのやり取りであれば、フロー型は過去の履歴を遡る事で、意図や経緯を理解出来るので便利です。
しかし、**連続性のあるトピック**の中に急に**非連続性のタスク**を依頼する人がいます。
これってむちゃくちゃで、受け取った相手は、気づかない場合が多いし、気付いたとしても、一瞬見ても、フローで流れて別のトピックになってると、自分で遡ってタスクを探さす必要があります。
一方、ストック型のコミュニケーションツールであれば、急に**非連続性のタスク**を依頼しても別メールとして残ってます。1通づつ確認する事が出来ます。
もちろん、slackなら自分へのメンションだけ見れる様になってますが、メッセンジャーやlineとかだと自分で一生懸命探さないとだめ、これはもう最悪です。slackは、スレッド化も出来るので更に便利ですね。
ただslackも既読つけると探す必要が出てくる点ではやはりフロー型のコミュニケーションツールです。

# 困ったストック型とフロー型の使い方
上司：来週から目標設定面談を開始するので、皆さん面談シートの記入を今週中にお願いします
あなた：わかりました。
同僚A：面談シートは、2022版の奴が最新版でしたよね？
上司：そうだね。2022版で。
先輩A：わかりました。
---1時間後
あなた：ところでプロジェクトの見積もりチェックお願いします
客先の上司：チラ見。
---1時間後
同僚A：面談シートは、メールで送りました。
上司：了解。
先輩A：面談シートは、メールで送りました。
---3日後
あなた：見積もりチェックいかがでしょうか？
上司：おっと、見落としてた。。。
**見積もり間に合わずに失注できました。**

# 正しいストック型とフロー型の使い方
上司：来週から目標設定面談を開始するので、皆さん面談シートの記入を今週中にお願いします
あなた：わかりました。
同僚A：面談シートは、2022版の奴が最新版でしたよね？
上司：そうだね。2022版で。
先輩A：わかりました。
---1時間後
あなた：ところでプロジェクトの見積もりをメールで送っておきました。チェックお願いします
客先の上司：チラ見。
---1時間後
同僚A：面談シートは、メールで送りました。
上司：了解。
先輩A：面談シートは、メールで送りました。
上司：メールで見積もりみたいよ。納期が入ってないので納期入れたらOKです。
**無事に受注できました。**

# ストック型とフロー型の特性を理解して利用しましょう
ストック型には、ストック型の良さ、フロー型には、フロー型の良さがあります。各々の特性を理解せずに自分勝手なコミュニケーションを取っていると相手が困るし、仕事が滞るばかりです。社内の人間であれば、それだと気づかないのでチケット切ってくれと言われるかもしれませんが、外部の方だと言いづらい可能性もあります。
ツール一つとっても常にメリット・デメリット等の特性を理解しながら使う様に気をつけるとビジネスレベルが1段アップすると思います。
# お願い
今後も続けていきますので、フォロー、イイね、シェアお願いします。
下記、説明会もご参加下さい。
[エンジニア年収アップ講習(転職サポート付き！)　無料説開会　12月6日　19時開催](https://cto-can-be.hp.peraichi.com/)
dockerを使ったPHPの環境構築

ただの覚書です。

```docker-compose.yml```
```yml 
version: '3'
services:
  #MySQL用コンテナ
  mysql:
    container_name: db
    image: mariadb:10.4
    volumes:
#./dataフォルダに作成してる
      - ./data:/var/lib/mysql
    environment:
        - MYSQL_ROOT_PASSWORD=root
        - MYSQL_DATABASE=todo
        - MYSQL_USER=todo
        - MYSQL_PASSWORD=todo  
    ports:
        - 3306:3306
  #php用コンテナ
  php:
    container_name: php-apache
#./phpフォルダに作成してる
    build: ./php
    volumes:
#./sourceフォルダに作成
      - ./source:/var/www/html
      - .php/vhosts.conf:/etc/apache2/conf-enabled/vhosts.conf
    ports:
      - 8000:80
    depends_on:
      - mysql
```

```Dockerfile```
```Dockerfile
FROM php:8.1.12-apache
#php install
RUN apt update
RUN apt install -y wget git unzip libpq-dev
RUN apt install -y zlib1g-dev mariadb-client libzip-dev libonig-dev \
    && docker-php-ext-install zip pdo_mysql

#composerインストール
RUN curl -sS https://getcomposer.org/installer | php \
  && mv composer.phar /usr/local/bin/composer \
  && chmod +x /usr/local/bin/composer

#ワーキングディレクトリ（ここで動く）
WORKDIR /var/www/html

#基本的には変わらない↓
ENV COMPOSER_ALLOW_SUPERUSER 1
ENV COMPOSER_HOME /composer
ENV PATH $PATH:/composer/vendor/bin
# タイムゾーン設定
ENV TZ=Asia/Tokyo
```

```vhosts.conf
NameVirturalHost *:80
<VirtualHost *:80>
    ServerAdmin todo@localhost
    ServerName localhost
    DocumentRoot /var/www/html/public
    <Directory "/var/www/html/public">
        Options Indexes FollowSymLinks
         DirectoryIndex index.php
         AllowOverride All
         Require all granted
         Order allow,deny
         Allow from all
    </Directory>
</VirtualHost>
```
Sailを使ったLaravelの環境構築(Docker)

<h1>Dockerでの環境構築は大変だと思っていた</h1>
<p>ずっとローカルに環境構築し続けて半年。Dockerを使い始めて一週間。いくつかのプロジェクトを作って感じたことがある。
Dockerfileとdocker-compose.yml毎回書くのめんどくさすぎる。これなら正直ローカアルに環境構築した方が早いし個人開発だけなら困らないと思っていたが、実務では使うと思い使っていたところに僥倖</p>

`curl -s "https://laravel.build/example-app" | bash `
これを使えば一撃でプロジェクトの作成ができる。。。教えてくれる人がいない為知りませんでした。
公式ドキュメントにはこうある。
https://laravel.com/docs/9.x/installation#main-content
## macOS での開始

Mac で開発していて、Docker Desktopが既にインストールされている場合は、単純なターミナル コマンドを使用して、新しい Laravel プロジェクトを作成できます。たとえば、 **「example-app」** という名前のディレクトリに新しい Laravel アプリケーションを作成するには、ターミナルで次のコマンドを実行します。

`curl -s "https://laravel.build/example-app" | bash`

もちろん、この URL の **「example-app」** は好きな名前に変更できます。ただし、アプリケーション名には、英数字、ダッシュ、およびアンダースコアのみが含まれていることを確認してください。コマンドを実行したディレクトリ内にLaravelアプリケーションのディレクトリが作成されます。

**Sail のインストールには、Sail のアプリケーション コンテナがローカル マシン上に構築されるまで数分かかる場合があります。**

プロジェクトが作成されたら、アプリケーション ディレクトリに移動して Laravel Sail を起動できます。Laravel Sail は、Laravel のデフォルトの Docker 構成と対話するためのシンプルなコマンドライン インターフェイスを提供します。

---

`cd example-app && ./vendor/bin/sail up`コマンドを実行して `cd example-app` でディレクトリを移動して `./vendor/bin/sail up`でコンテナを立ち上げると何も書かずに環境ができた。
もちろんDockerfileやymlを編集していくことは可能だった。備忘録として覚えておきたい。

追記：MySQLの文字化けが起きる可能性を考慮して、追加でmy.cnfの作成とtDatabase.php、docker-compose.ymlを変更しておく
paiza.ioでelixir その103

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
10を与えて、「合計: 10」を、パイプラインでプリントせよ。


# サンプルコード

```
10
|> to_string
|> String.split(" ")	
|> Enum.map(fn x -> 
	IO.puts("合計: #{x}")
end)
```

# 実行結果

```
合計: 10
```

# 成果物


https://paiza.io/projects/LIbCFk18bLDT4aDKN4C4yw


以上。
MATLAB で Digital Lossy VST プラグインを作る ～ 聴覚心理特性とは？ ～ 非同期バッファで MDCT（予告編）

[<B>MATLAB/Simulink Advent Calendar 2022</B>](https://qiita.com/advent-calendar/2022/matlab) に参加予定です。
<br>
プラグイン自体はすぐ書けたけど、解説記事書くのにすでに計3日徹夜しました！
普通の記事は、ある程度下調べしておけばたいてい一晩で書けるのに・・。
間に合うのか？（；￢＿￢）
<br>

・使用ツール
<dt>　MATLAB</dt>
－Audio Toolbox
<br>
<br>

・デモ動画
<B>[Digital Lossy VST プラグイン]</B><iframe width="374" height="665" src="https://www.youtube.com/embed/-bc6Bvvey80" title="Digital Lossy Plugin" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<B>[Digital Lossy Plugin (audioTestBench)]</B>
<iframe width="919" height="349" src="https://www.youtube.com/embed/fN_BvLdK3b8" title="Digital Lossy Plugin (audioTestBench)" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

<br>
<br>
<br>
<H4>[<B>note</B>]<a href="https://note.com/leftbank/"</a> にUpします。</H4>
glTFに書き出してthree.jsで使う前提のBlenderデータでの命名

## この記事の概要

Blenderでは要素を複製すると、`元の名前.001`、`元の名前.002`というルールで名付けられます。
three.jsで`if (object.name === 'Cube.001')`のようなコードを書いた際に動かなかったので、挙動を調べました。
その上で「こういう命名がいいのでは？」と考えたので記事にしてみました。

ただ、世間の常識というよりは個人的な考えのまとめなので「それは違うんじゃないの？」などがあればコメント or 編集リクエストをお願いします :bow:

## 今回たどり着いた結論

名前が重複する要素は、以下のどちらかの命名にしておくのが良さそうです。

- `Mesh`、`Mesh_001`、`Mesh_002`
- `Mesh_000`、`Mesh_001`、`Mesh_002`

上の命名ならもともとのBlenderの命名から、`.`を`_`に置き換えるだけで良いので楽そう。
下の命名ならループを回して「名前が合致したら云々」のようなコードを書く際に楽そう、という理由です。

## 調査

以下の表のようになりました。

| Blenderでの名前 | .glbでの名前 | three.jsでの名前 |
| --- | --- | --- |
| Mesh | Mesh | Mesh |
| Mesh.001 | Mesh.001 | Mesh001 |
| Mesh 001 | Mesh 001 | Mesh_001 |
| Mesh-001 | Mesh-001 | Mesh-001 |
| Mesh_001 | Mesh_001 | Mesh_001 |

### 環境

| ソフト、ライブラリ | バージョン |
| --- | --- |
| Blender | 3.3.1 |
| three.js | 0.146.0 |

### 確認した方法

1. Blender上で`Mesh`という名前の要素を作成し、`.`、`スペース`、`-`、`_`を用いて名前をつける
1. 書き出した`.glb`ファイルを開き、内容を確認する
1. `if (object.isMesh) console.log(object.name);`でコンソールに名前を出力して確認する

## 最後に

Blenderで書き出し用データを作る際、Modifierをapplyしておくべきなのと同様に、名前もちゃんとつけておいた方が良いなと思いました。

あと、.glbファイル内ではスペースやピリオドを含んだ名前として記載されているのに、three.jsで読むと勝手に変わるんだ……と驚きはしました。

---

最後まで読んでくださってありがとうございます！
Twitterでも情報を発信しているので、良かったらフォローお願いします！

https://twitter.com/xrxoxcxox

Devトークでのお話してくださる方も募集中です！

https://jobs.qiita.com/employers/qiita-inc/dev_talks/489
2022/11/28主にITとかセキュリティの記事

スマートフォンは安全保障の最前線になった IT競争政策はサイバー攻撃のリスクを考慮せよ(11/26)
https://toyokeizai.net/articles/-/634785

スマホ決済が１日７２３２億ウォン、早まる「財布不要」時代の到来(11/26)
https://www.donga.com/jp/home/article/all/20221126/3786358/1

今話題の脆弱性について自社サイトは大丈夫ですか？(11/25)
https://qiita.com/motoyasu-yamada/items/1afc3555b5275a2de46e

GoogleがVLCになりすましてマルウェアを配布するページの削除を拒否したとVideoLAN公式が告発(11/25)
https://gigazine.net/news/20221125-google-vlc-fake-page-refuses-take-down/

＜Kaspersky Security Bulletin：2023年APT攻撃の動向予測＞新たなWannaCryやドローンを使用した近接ハッキングが起こる可能性を予測(11/25)
https://www.jiji.com/jc/article?k=000000329.000011471&g=prt
Railsで効率的に列を捌ける仕組みを考える

# ルール
作業可能レーンに順番にかかる作業時間がバラバラなタスクが流れてきて、最終的に作業可能レーンにタスクがなくなる時間を知りたい

## 具体的に
`times`には、作業にかかる時間が適当な数定義されており、
`till`は作業可能レーン数が定義されている。
最終的に全部の`tills`で作業が終わる時間が知りたい。

```ruby
times = [3,4,5,6,7,8,9,20,30]
till = 5
tills = Array.new(till, 0)
# => tills
# => [0, 0, 0, 0, 0]
```


# 求め方
`times`をeachでまわし、`tills`の中で一番作業時間が少ない`列`をindex()の引数に持ち、
その列をtillsから特定して、eachの値を加算していく.

```ruby
times.each {|time| tills[tills.index(tills.min)] += time}

tills.max
#> tills
#=> [11, 13, 25, 36, 7]
#> tills.max
#=> 36
```
RailsでCSVファイルをインポートする方法改

CSVファイルをインポートしてデータベース/テーブルに登録って段取りは結構メジャーで、既に幾つも解説記事が上がってる。その節はお世話になりました。

前はその通りにやって出来たのだけど、今新しいプロジェクトでソースを使い回すと何故か出来ない。確実ではないけど、ひょっとしたらrailsかrubyのバージョンによって出来ないとかあんのか？となったので、今できてるものを以下にメモ的に置いておきます。少なくとも自分はこれで半日潰しました。

バージョンはruby 3.04、rails 6.1.7です。ちゃんとした仕組みとか解説は他を読んだ方がいいよ。

## Gemfile
とりあえず

```Gemfile
    gem 'roo'
```
bundle installとかもしておくように。

## application.rb
一応csvのrequireを書いておく
```config/application.rb
reuire "rails/all"
require 'csv'
```


## views
ここが以前と特に違う。
以前は参考にしたサイトはどこも、パスの指定がimport_hoge_pathのように、**アクション名_コントローラー名_path**という表記されていた。実際に以前はこの表記で通っていたけど、現状ではなぜか通らないので通常のコントローラー名_アクション名_pathの記法とする。理由は何かあるんだろうけどわからない。

一応いうと、hoge_controllerと紐付いてる前提です。

```hoge/test.html.erb
  <%= form_with url: hoge_import_path do |form| %>
    <%= form.file_field :file, accept: '.csv' %>
    <%= form.submit "インポート" %>
  <% end %>
```

## Routes
ここも参考サイトはどこもかしこも判で押したようにresourcesで指定していたが、とくにresourcesでなきゃいけない理由もないと思うので普通に指定

```config/routes.rb
post 'hoge/import' => 'hoge#import'
```
## controller
Userモデルにデータをぶちこむというサンプル。ここからは先行の参考サイトと全く同じ。

```app/controllers/hoge_controller.rb

def import
    User.import(params[:file])
    redirect_to root_url
end

```

## model
モデルのところまで持ち込まれたファイルをデータにぶちこんでいく作業。
ここでは名前が既存データになければ登録していくという仮定になっている。
```/app/models/user.rb
class User < ApplicationRecord
    def self.import(file)
      CSV.foreach(file.path, headers: true) do |row|
        #nameが見つからなければ新しく作成
        user = find_by(name: row["name"]) || new
        user.attributes = row.to_hash.slice(*updatable_attributes)
        user.save
      end
    end
  
    def self.updatable_attributes
      ["name","address","age","phone"]
    end
end
```

ほとんどコピーみたいなもんなんで、すみません。
エンコード直すのとかも入れてもいいかもだけど、まぁとりあえず。
【Node.js】コールバック地獄の関数からPromiseを使って同期処理後に値を取得する

## はじめに
意外と検索してパパっと出てこないので記事化してみました。

Azure上のMySQLとの接続処理をコーディングしていたので、サンプルのコードはMySQLのusersテーブルからデータを取得する処理をイメージしています。

## 実現したいこと
async/awaitを使って非同期処理内で関数を同期実行して、返り値を同期的に取得したいケースがあるんじゃないかと思います。
```sample.js
(async function() {
    response = await requestApi();
    console.log(response);
})();
```
<br>

Promiseを返してくれる関数だったら楽でいいのですが、例えば下記のようにコールバックにコールバックを重ねている関数を全て同期処理させた後、値を取得するにはどうすればいいのでしょうか。

```dbaccess.js
import * as mysql from 'mysql';
import * as fs from 'fs';
import * as dotenv from 'dotenv';

const config = {
  host: process.env.HOST_NAME,
  user: process.env.DATABASE_USER_NAME,
  password: process.env.DATABASE_USER_PASSWORD,
  database: process.env.DATABASE_NAME,
  port: 3306,
};

//DBの接続情報設定
const conn = mysql.createConnection(config);

//DBのコネクション処理
conn.connect(function (err) {
  if (err) throw err;
  //SQLの設定、データ取得
  conn.query('SELECT * FROM users', function (err, results) {
    if (err) throw err;
    //[!]このresultsがほしいケース
    console.log(results);
  });
  //DBのコネクション切断
  conn.end(function (err) {
    if (err) throw err;
  });
});
```

## 解決策
Promiseを返してくれる関数を用意してあげて、コールバックの関数を書いていく、そして関数の一番最後でresolveを呼んであげます。

サンプルコードは下記の通りです。

```dbaccess.js
~~~~前半は省略~~~~

//DBの接続情報設定
const conn = mysql.createConnection(config);

const fetchUsers = () => {
  return new Promise((resolve) => {
    //DBのコネクション処理
    conn.connect(function (err) {
      if (err) throw err;
      //SQLの設定、データ取得
      conn.query('SELECT * FROM users', function (err, results) {
        if (err) throw err;
        resolve(results);
      });
      //DBのコネクション切断
      conn.end(function (err) {
        if (err) throw err;
      });
    });
  });
};

const users = await fetchUsers();
console.log(users);
```

## 参考
[コールバック関数の同期実行と非同期実行](https://zenn.dev/estra/books/js-async-promise-chain-event-loop/viewer/4-epasync-callback-is-sync-or-async)
[teratail コールバック関数から値を返したい](https://teratail.com/questions/119949)
[クイック スタート: Node.js を使って Azure Database for MySQL フレキシブル サーバーに接続してデータのクエリを実行する](https://learn.microsoft.com/ja-jp/azure/mysql/single-server/connect-nodejs)
Data Warehouse構築の際の各ロールへの権限の委譲のやり方

※今後加筆修正する可能性あり(2022.11.27現在)

　Snowflakeを使ってデータウェアハウス(Data Warehouse 以下DWH)の構築を行った。DWH内に複数あるテーブルに対して、各ロールごとにアクセスの権限を付与する際、<U>すべてのテーブル</U>に一括で権限を付与する方法が難しかったので、忘れないためにまとめる。

対象：初めてSnowflake上にデータベース・スキーマ・テーブルを構築する人
筆者の経験値：初めてSnowflakeを扱う
この記事の目的：ロールに対して、複数のテーブルに一括してアクセス権限を付与する方法

<b>ロール</b>
　SnowflakeでDWHを構築する際、DWHを設計する人・閲覧する人・DWH内のデータを使う(挿入更新削除)人のように、役割に応じてDWHにアクセスする権限を切り替えたい場合がある。(例：データを見るだけの役割の人がデータを勝手に更新・削除できてしまってはデータの管理上問題がある。データを見るだけの役割の人にはデータを見る権限のみを与えるようにしなければならない)
　これらの役割をロールという。

<b>ロールへの権限付与で生じた課題</b>
　SnowflakeはSQL文を叩くか、GUIで操作することでアクセス権限を付与できる。たとえば、SQL文で特定のテーブルに権限付与するとしたら以下のようになる。
> grant usage
  on database d1
  to role r1;

>grant usage
  on schema d1.s1
  to role r1;

>grant select
  on table d1.s1.t1
  to role r1;

しかしこのやり方だと、1個1個のテーブルにいちいちSQL文を書いては実行書いては実行…を繰り返さなければならずめんどくさい。

<b>各ロールへの権限を一括付与</b>
>grant select 
 on future tables in database d1 
 to role r1;

　「未来のテーブルに対して権限を付与する」ということにすれば、テーブルを作成するごとに付与した権限が適用されるので、便利！

<b>参究</b>
※以下、よくわかっていないこと
　上述のやり方では、「未来のテーブルに対して」権限を付与する内容だが、既存のテーブルにも一括で権限を付与したい時はどうしたらいいのか...?

　Snowflakeの使い方やエラー解消に関する日本語のサイトが公式ドキュメント以外に乏しく、今回Qiita記事を書くに至った。今後Snowflakeを扱う人に参考に慣れればと思う。

<b>参考</b>

https://docs.snowflake.com/ja/user-guide/security-access-control-configure.html#grant-privileges-to-the-role

https://docs.snowflake.com/ja/user-guide/security-access-control-overview.html
Neo4jの起動エラー

spring bootがエラーで起動せず。
そもそも、neo4jをstartする時点で、以下エラーになっていた。
```
org.neo4j.cli.CommandFailedException: Failed to read config /opt/homebrew/Cellar/neo4j/5.2.0/libexec/conf/neo4j.conf: Unrecognized setting. No declared setting with name: wrapper.java.additional.4. Cleanup the config or disable 'server.config.strict_validation.enabled' to continue.
```
上記にあるように、server.config.strict_validation.enabled=falseを設定してみたら、一応neo4jは起動したが、以下ワーニングは出ていた。
```
Starting Neo4j.
WARNING! You are using an unsupported Java runtime.
* Please use Oracle(R) Java(TM) 17, OpenJDK(TM) 17 to run Neo4j.
* Please see https://neo4j.com/docs/ for Neo4j installation instructions.
Started neo4j (pid:12089). It is available at http://localhost:7474
There may be a short delay until the server is ready.
```
openJDKのバージョンが古いらしい。
Macでjavaを複数管理して切り替える方法を模索すればできるかも。

以下、調べた事とか。
https://qiita.com/yamato999/items/283a0779709bb7a9cbda
madでjavaのバージョンを複数管理し、切り替える方法

neo4jの起動でjavaバージョン（openjdk15系が古くて、17系じゃないとダメ的なワーニングが出た）ワーニングに派生して調べた事の備忘。

以下、参考サイト
https://amateur-engineer.com/mac-java-version/
https://qiita.com/ponsuke0531/items/795cd00d93b71c14d07b
https://hitori-goto.com/2021/01/27/mac-install-openjdk/
https://qiita.com/takayamag/items/1469c59370df348240f8
https://phoeducation.work/entry/2021/01/13/134223

下手にいじったら私のmac内のjavaプログラムが色々と動かなくなったらコワイので、なかなか実行する勇気が無いが、機会があったら試してみたい。
□豆腐□からの脱却

# □豆腐□からの脱却

せっかくあれこれ作ったのに、なんだかUnity上の見た目が□□□□だらけで訳が分からない！
これは、TextMeshProやunity標準で入っているフォントが日本語に非対応だから起きる現象です。
逆に言うなら日本語対応のフォントさえ入れればこの□豆腐□から脱却できるはずです。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/2c5e789c-d5c9-48d1-f9f0-952afc149ccd.png)

- フォント
　バーチャルキャストの公式にフォントについて触れられています。
　https://virtualcast.jp/wiki/vci/component/sdk/text#%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%81%AB%E9%96%A2%E3%81%97%E3%81%A6
　
　ここにならい、[TMP_NotoSansCJK.unitypackage](https://github.com/virtual-cast/VCI/releases/download/v0.23/TMP_NotoSansCJK.unitypackage)からアセットをダウンロードしましょう。

- インポート
　ダウンロードしたらインポートだよね、
　「TMP_NotoSansCJK.unitypackage」を「Assets」へドラッグアンドドロップにてインポートしましょう。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/7f0a7780-f821-0c6f-408d-b967039f0e31.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/cab57722-9635-94a5-985b-8b4c06730aef.png)

　これで日本語フォントのインポートが完了しました。

- フォントを入れ替えよう
「フォント は 入れ替えない と 意味がないぞ」

　ということでフォントを入れ替えていきましょう。
　ヒエラルキーからフォントが入っているオブジェクトを選択し、
　「TextMeshPro」→「Font Asset」の、◎をクリックしましょう。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/28b8b93c-8001-259a-e712-35a49f6adefd.png)

- フォントを選ぼう
フォントのリストが出てきましたね。
そこから「**NotoSansCJK-Bold_SDF**」をダブルクリックで選択しましょう。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/0c36efa8-e654-f52c-0adc-6266e9391268.png)
　 これでフォントが適応されました。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/807db99d-e4bb-3b84-7536-da9f6ae9a32b.png)

- どんどんフォントを入れ替えよう。
Unityは便利な機能があっていいですね。
ヒエラルキーで複数選択し、まとめて共通事項が変更できますから。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/9b5d7626-6d43-dee7-4a59-18c43df8fd19.png)

　入れ替えが完了し豆腐から脱却できました。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/80b5d3e7-fa3f-bb0f-844f-640e3782d264.png)

- ちなみに・・
　フォントデータは自作したり、他から手に入れたものと入れ替えて使用することが可能です。
　しかしバーチャルキャストでは使用できるフォントが 「**NotoSansCJKjp-Bold**」で固定
　されているため、いくら変えてもUnity上での表示だけが変わるということになります。


- テキスト増やすたびにフォント入れ替えるのめんどくさくない？
　ということで、せっかくなのでフォルト設定を変更しましょう。
　「編集(Edit)」→「プロジェクト設定(Project Settings)」
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/869ed544-1377-580b-8f2d-59120cd762d9.png)

　「TextMesh Proの設定(Settings)」→「Default Font Asset」の◎から
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/7859b616-2faa-2079-2a33-6f47b5cbb01e.png)

　先ほどと同様にフォントリストから「**NotoSansCJK-Bold_SDF**」を選びましょう
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/4c794fa8-b70f-6947-4669-8221f0118338.png)

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2353185/3e7d4625-64e3-6d55-0943-683c9ff5ddce.png)
これでデフォルトフォントを変更することができました。

# ひとこと
そんなことより湯豆腐食べたい。
Eclipseの米粒アイコンをPythonで大きくした話

# めでたし、めでたしのはずが
「今さらEclipse」シリーズ、第3弾。前回、SWT（Standard Widget ToolKit）のパラメーターによってUI全体の拡大をスマートにやっつけたはず、だったのだが、野蛮にもPythonでリサイズしてしまった。
（参考）シリーズ[第1弾](https://qiita.com/naohiro2g/items/4f0c66a2ff5eb79fe76d)、[第2弾](https://qiita.com/naohiro2g/items/dde897c0b510391182e0)

なぜかというと、気になることがいくつかあり。
 - UI全体の拡大だと、ウィンドウのマージンやファイルリストの行間など、全てが拡大されて大味な感じになること
 - エディターペインにゴミ、細い横線が時々表示されること（スクロールすれば消えるが）
 - アイコン画像を全部リサイズしてしまったらどうなんだろ、と思いついてしまったこと

アイコンのリサイズをJavaでやったら入門者らしかったのだが、いかんせん、初心者すぎて、そのレベルに達するまで待てない。ので、Pythonで。

# とても野蛮
Eclipse/Pleiadesのインストール先、C:\pleiades\2022-09\eclipse以下にある、すべての16x16ピクセルのpng/gifを狙い撃ち、28x28ピクセルにリサイズ。

前回、補完方法をnearestからsmooth（アルゴリズム名は不明）に変えて改善されたが、今回は、一番良さげなLANCZOSにて。

早速コードを。Pythonはお気楽だ。

```py
# enlarge eclipse icons
import os
from PIL import Image

SIZE_FROM = 16
SIZE_TO = 26

old_path = ""
for path, dirs, files in os.walk(r"C:\pleiades\2022-09\eclipse"):
    for file in files:
        file_path = os.path.join(path, file)
        for ext in ".gif .png".split(" "):
            if (ext == file_path[-4:]):
                img = Image.open(file_path)
                if img.size == (SIZE_FROM, SIZE_FROM):
                    if (path != old_path):
                        print("\n", path)
                        old_path = path
                    print(img.size[0], img.size[1], "\t", file)
                    img = img.resize(size=(SIZE_TO, SIZE_TO), resample=Image.LANCZOS)
                    img.save(file_path)
# print("\n{}-pixel icons enlarged to {}.".format(SIZE_FROM, SIZE_TO))

```
## アイコンが入っている場所

ほとんどのアイコンは、
```"C:\pleiades\2022-09\eclipse\configuration\org.eclipse.osgi"```にあり、さらに、```"C:\pleiades\2022-09\eclipse\configuration"```までで、ほぼ全てカバーしているが、結局、若干残ったため、eclipseディレクトリ全体を対象に。
言わずもがな、バックアップを取っておくことをおすすめ。まぁ、戻したければ、再インストールでも良い。


## ビフォア／アフター

16ピクセルから26ピクセルなので、162.5%。しばらく大きなアイコンで使っていたため、Eclipseの理解も深まり、アイコン識別力が上がってきたようで（笑）、これでもちょっと大きいか？となった。


ビフォア 100%
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5412/ad96e680-f862-9125-b398-9b5d7c4772d7.png)

アフター（１） SWTによるリアルタイム変換、170%
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5412/d13f04d5-5c9d-7ea1-47d4-18b1f4855fb5.png)

アフター（２） Pythonによる一括変換、162.5%
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5412/c380d4c5-667d-3bc6-3ad2-c6ba7ed85889.png)

やはり、LANCZOSによるリサンプリングはキレイで、やった甲斐有り。
Javaコーディング、デバッグ、Git、全部入りのよくばりセットでちょうど収まった。

追記：Gitのアイコンはここになくても良い。「Gitリポジトリー」ペインなどのファイルのコンテクストメニューやツールアイコンでの操作のほうがわかりやすい。

## 取り残されたアイコンたち

正方形でない画像も結構あるが、これらは拡大されない。ペインの最大化、最小化、復元、ツールアイコンの「グループ内仕切り（点線）」、「X（閉じる）」、など。このままで良い。

「パッケージ・エクスプローラー」のリスト部分のアイコンが小さいまま。こいつらは、エラーのバツ印などのステータス変化をなんと合成で実現していると思われ、取り残され組。しかし、逆にコンパクトになって良かった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5412/b6ac791c-71bf-8768-93ab-7a1d7832743b.png)

一方、「Gitリポジトリー」のリストは、アイコンが大きくなっているため、行間が増加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5412/ad4c0530-3c66-89c6-000f-191d9009d8e2.png)

下部ペインも同じく、よくばりセットで、ちょうどお腹いっぱいになり、いい感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5412/fbcf9d09-c3dc-86b3-ee64-9ee399440c13.png)

今のところ目立った不具合もないので、使い込んでみようと思う。
Mac環境でssh -X接続しようとも応答がなかったので色々確認した際の備忘録

Mac環境でssh -X接続しようとも応答がなかったので色々確認した際の備忘録

以下を参考に自宅のubuntu環境にMacで`$ssh -X`により接続しようとしたところ応答がない、、

> X11 ForwardingしてMacにGUI表示する
> https://qiita.com/loftkun/items/37340745f211ea5d7ece

```
$ ssh -X ubuntu@192.168.0.4
(応答がない)
```

色々調べると[`Xquartz`(macOS上でX Window Systemが動くオープンソースソフトウェア、いつもお世話になります)](https://www.xquartz.org/)が上手く動いておらず再インストールすることで解決
久しぶりに実行したので調子が悪かったのだろうか。。

# 参考

https://qiita.com/loftkun/items/37340745f211ea5d7ece
【Go言語】翌月末を求める

Go言語で翌月末を求める方法について記載してみました。

# 単純なAddDateではだめ

## 7/31の１ヵ月後
月を+1した場合に存在する日付の場合はOK。
``` go
t, _ := time.Parse("2006/01/02", "2023/07/31")
fmt.Println(t.AddDate(0, 1, 0))
```
```
// 出力
2023-08-31 00:00:00 +0000 UTC
```

## 8/31の１ヵ月後
月を+1した日付（9/31）は存在しない。
これを存在する値に変換する処理が走り10/1となります。（これをGoの正規化と呼びます）
``` go
t, _ := time.Parse("2006/01/02", "2023/08/31")
fmt.Println(t.AddDate(0, 1, 0))
```
```
// 出力
2023-10-01 00:00:00 +0000 UTC
```

# 月初の２ヵ月後の１日前を求めればよい
8/31の月初は8/1、その２ヵ月後は10/1。
その前日は9/30なので求めたかった翌月末となります。
```go
t, _ := time.Parse("2006/01/02", "2023/08/31")
// 月初
t = time.Date(t.Year(), t.Month(), 1, 0, 0, 0, 0, time.UTC)
// ２ヵ月プラスし１日マイナス
fmt.Println(t.AddDate(0, 2, 0).AddDate(0, 0, -1))
```
```
// 出力
2023-09-30 00:00:00 +0000 UTC
```

# The Go Playground
いろいろ試せるようにGo Playgroundに書いたコードをリンクしておきます。
https://go.dev/play/p/WChOkFZr6qs
io/fs でのエラー解決方法 "cannot load io/fs: malformed module path "io/fs": missing dot in first path element" 

* エラー内容
* io/fsとは？
* 解決方法

# 1.  エラー内容
いつも通り、go言語でプログラムを書いていると、
```
cannot load io/fs: malformed module path "io/fs": missing dot in first path element
```

どうやらio/fsが認識していない模様...
そもそもio/fsとはなんぞや？

# 2. io/fsとは？
Go1.16からio/fsパッケージとして導入されました。
主に、ファイルシステムの抽象化の役割を担い、例として、ZIPファイル等をサードパーティライブラリを使わずにGoのみで埋め込めるようになったりします。
保守のしやすさと、可読性が向上したといえるでしょう。

# 3. 解決方法
今回の場合は、io/fsがGo1.16から導入されたとのことで、私が使っていたGo1.13では対応していませんでした。なので、使われる方は、バージョンをアップして使用しましょう。

https://qiita.com/yuta_vamdemic/items/43fc04d98182f7bb83d4


上記の方はパス名まで変更する必要があったみたいです。参考までにどうぞ。
「curl」の読みは「カール」が正解

下記のツイートを読んで (不安になって) `curl` の読みについて調べたところ、「カール」が正解だったので残しておく。

https://twitter.com/yamada_sier/status/1595235715381481472


エビデンス
----

curlの公式サイトにそう書いてある。

https://curl.se/docs/faq.html#What_is_cURL

> We pronounce curl with an initial k sound. It rhymes with words like girl and earl.


cURL
----
Wikipediaなどで `cURL` という表現を見るが、前述の公式サイトでは一貫して `curl` という表現をされている。

https://ja.wikipedia.org/wiki/CURL

~~`cURL` という表現は一体どこから生まれたんだ・・・（何か知っているかたはコメント頂けると嬉しい）。~~

公式サイト 1.1に普通に書いてました :innocent: 

> 1.1 What is cURL?
> cURL is the name of the project. The name is a play on 'Client for URLs', originally with URL spelled in uppercase to make it obvious it deals with URLs. 
...
> The cURL project produces two products:
> libcurl
> curl

まとめると、プロジェクトを指す場合は「シー・ユーアールエル」でも間違って無くて、コマンドを指す場合は「カール」ってことか。
ZennとGitHubを連携させる方法

ZennとGitHubを連携させる方法を紹介します。

**Zenn CLI** で記事を書くためには、事前にGitHubと連携させておく必要があります。

## 準備

ZennとGitHubを連携させる準備をします。


## GitHubのアカウントを作成

GitHubのアカウントを作成し、GitHubを使えるようにします。

https://github.co.jp/


## リモートリポジトリを作成

「New」をクリックして新しい **「リポジトリ」** を作成します。

ここでは **「zenn_connect」** という「リポジトリ」を作成します。


#  Zennにログイン

アカウントの **「ロゴ」** をクリック

**「GitHubからのデプロイ」** をクリック

画面下の **「リポジトリを連携する」** をクリック





## ユーザー認証

**GitHub** の

**「ユーザーネーム」** もしくは **「メールアドレス」**

**「パスワード」**

を入力します。



## 共有リポジトリを指定する

GitHubの認証が済むと、

**Install ＆ Authorize Zenn Connect**

という画面が表示されます。

その下にある **「Only select repositories」** を選択します。

GitHub上で作っておいたリモートリポジトリ **「zenn_connect」** を選択します。

以上で終了。これでZenn CLIで記事を書く準備ができました。
タミヤ・ローラースケートロボの改造

■タミヤ・ローラスケートロボをrasPI-3Aで動かしてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/77a9892d-82fa-ebc1-aa22-e42b06c37bff.png)
-
■タミヤ・ローラースケートロボとは
両脚を左右に開閉させてすべるように前に進む(スウィズル)、ローラースケートを装備したロボット(@2420)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/12fba674-d148-6b72-42f5-be2f800b680e.png)
-
■追加部品
・ Raspbery Pi-３A
・ モータ制御モジュール(DRV8830-I2C)
・ 電源：昇圧モジュール(3.7v→5v)
・ ソフトPWM用基板(6ch)（自作）
・ 電池：14500(Lipo 単三電池サイズで 3.7v）＋モバイルバッテリ
・ ジョイスティック(F710)
・ LiDAR-LD06(38.6mmキューブで42g 12mまで)回転が中で安全
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/fc22ef2b-78da-dd5e-44f6-b61703d5a779.png)
-
■取り合えず・・ロボットの組み立て
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/81ad4c46-d0dc-9367-a798-24340bde24f2.png)
-
■ロボットの組み立て-2
  マイクロサーボをブラックの底が平坦のに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/1476a73b-7912-2660-b72a-9d7380c35973.png)
-
■左右制御の動作確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/e9df0035-42cc-c94e-476a-21fed06ee54b.png)

https://twitter.com/i/status/1599038555661430784

-
■rasPI装着と動作確認でrasPIが飛ぶ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/d974878b-db28-6efa-f195-cdb4f02e4f24.png)
-
■動かしてみた(ジョイスティック操作)
![2022-04-17-02-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/93efe86e-d610-fdb8-ff80-287beda60e35.gif)

https://twitter.com/i/status/1599037939216154625

https://twitter.com/i/status/1599038110167609345

■LiDAR LD06を付けてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/2c40dcc5-6545-5bab-cdeb-9fd08f831c0c.png)
-
■LiDAR LD06をROS-rvizで確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551517/9f0180e4-138d-b86b-df50-ad98a705f1c1.png)
-
■最後に・・
・ローラスケートロボでは、ブレーキが無い!
  可動モータを停止しても、慣性で動いてしまいます。
  そこで・・スキーのボーゲンを参考に「プルークファーレン」で
  停止する方法で・・左右のサーボを広げて止める制御を入れた。
・やりたい事
　WEB操作を追加してみんなで外部から動かせたい。
   (前々回ngrok経由でロボット動かしたように)
　ROSで自律走行まで
　カメラも取り付けたい
　スピーカマイクも付けてお喋りも。。
Webの基本〜クライアントとサーバ〜

# はじめに
今回のテーマである`HTTP`は、Webエンジニアなら必ず抑えておきたいワードかと思います。
​
当方は2022年9月現在、バックエンドエンジニアとして従事してはや2ヶ月が経過しております。独学で学習をしていたとはいえ、このあたりの知識がかなり曖昧であったため、「頭の中の整理」という意味も込めて投稿したいと思います。
# そもそもHTTPとはなんぞや
HTTPは、「**H**yper **T**ext **T**ransfer **P**rotocol」の略です。
HTTPはRFC２６１６(※)で規定された、WebサーバとWebブラウザの間でWeb情報をやりとりするためのプロトコル(コンピュータでデータをやりとりするために定められた手順や規約)です。
クライアントはHTTPに従って**サーバ**に**リクエスト**を送り、レスポンスを得ます。
​
※`RFC`とはインターネット技術の標準化などを行う団体が発行している、技術仕様などについての文書群。「2616」は割り当てられた通し番号。最新の通し番号は8000番代。
​
# クライアントとサーバ
前述している`クライアント`や`サーバ`とはなんでしょうか。
クライアントは、「顧客」や「依頼人」という意味が、世間一般の認識だと思います。
イメージとしては割と近いです。
サーバはどうでしょうか。映画やドラマでたまに見る、「寒くて薄暗い部屋に所狭しと設置された黒い筐体が、緑色の怪しい光を放つ姿」を想像するのではないしょうか？
IT、Web業界における２つの言葉の意味をご説明します。
​
### クライアント
`client`という英単語の意味は本来、「顧客」や「依頼人」という、サービスや商品を`提供される側の人`のことを指します。
ITやWebの領域においても似たようなイメージをもって頂けたらと思うのですが、
クライアントは、`Webブラウザからコンテンツをリクエスト(取得)する側`、つまり`コンテンツを提供される側`のモノのことを指します。
例）　Chrome, Safari, Firefoxなど
### サーバ
サーバ（Server）とは、クライアントから送られたリクエストを、サーバ側で解析・処理してそれに対する回答(レスポンス)を提供するソフトウェアやコンピュータのことを指します。
# クライアントとサーバのやりとりを見てみよう
Chromeに標準搭載されている開発者用の検証ツールである、[Google Chrome デベロッパーツール](https://www.google.com/intl/ja/chrome/dev/)を使って、クライアントとサーバのやりとりのデータを確認することができます。
​
Chromeで、[Google](https://google.com)のトップページにアクセスしてみます。
トップページに遷移したら、
- macOSをご使用の方:Command + Option + i
- windowsをご使用の方：Ctrl + Shift + i
以上のショートカットキーを入力すると、ページ上にデベロッパーツールが表示されます。
![](https://storage.googleapis.com/zenn-user-upload/15bf82cce30a-20220922.png)
上部のバーにご注目ください。
Elements, Console, Sources, Network... といくつかタブが表示されているかと思いますが、今回はNetworkタブを使用します。
![](https://storage.googleapis.com/zenn-user-upload/ff6f8257f340-20220922.png)
すでにGoogleのトップページがレスポンスされているため、今は殆ど何も表示がありません。
ではこの状態で、ページの再読み込み(
- macOS：Command + R
- windows：Ctrl + R
)をしてみてください。
![](https://storage.googleapis.com/zenn-user-upload/b807f64c1567-20220922.png)
なにやらたくさん情報が表示されました。
一番上の項目、`www.google.com`をクリックしてください。
![](https://storage.googleapis.com/zenn-user-upload/b5c6ad7e6c2a-20220922.png)
この項目は、表示されているページのHTMLファイルの通信記録です。
クリックすると、HTTPヘッダの中身を確認することができます。
HTTPヘッダは、HTTPのリクエスト・レスポンスのやりとりのデータに関する説明書きを記載している部分のことです。
上部の「General」を簡単に読み解くと、『Googleのトップページにアクセスしたときにサーバに要求(※GET)したリクエスト(HTMLファイル)を、200でレスポンスしている』と記載されています。
'200'はHTTPステータスコード(Webサーバからレスポンスの結果を表す三桁の数字コード)の一つです。
#### HTTPステータスコード
HTTPステータスコードは5つのクラスに分類されています。
- 100~199：情報レスポンス
- 200~299：成功レスポンス
- 300~399：リダイレクトメッセージ
- 400~499：クライアントエラーレスポンス
- 500~599：サーバーエラーレスポンス
​
つまりここでは、「Googleのトップページを見せてほしい」というクライアントからのリクエストに対して、サーバー側のレスポンスが無事成功していることを意味します。
​
※`GET`とは、`HTTPメソッド`の一つです。次回以降の投稿でHTTPメソッドについて触れていきたいと思います。
# クライアントとサーバで行われていることのまとめ
ここまでの、クライアントとサーバのやりとりについてまとめると、
1. クライアントがリクエスト・メッセージを構築・送信
2. サーバがそのメッセージを受信・解析
3. サーバがアプリケーション（今回でいうとGoogle）に処理を委譲
4. アプリケーションからコンテンツを取得したサーバが、レスポンスメッセージを構築・送信
5. クライアントがサーバからのレスポンスメッセージを受信・解析
6. クライアント側でページを表示するための処理が行われる
以上のような流れとなります。
# 最後に
プログラミングやITの知識をキャッチアップする際、どうしても表立った部分（言語やフレームワーク、トレンドなど）が取り沙汰されがちな気がします。しかしこういった所謂「裏側」の知識をきちんと知っておくことで、より深い学びになると思います。
私自身こういった領域の知識習得が疎かになってしまっていましたが、今回記事にしたことでかなり学びになりました。
# 参考文献
山本陽平　著 . "Webを支える技術" . 技術評論社 . 2010年4月8日出版
Gitについてのアウトプット

## なぜGitについて学ぼうと思ったのか
　普段何気なく使っているGit。私はアプリの製作中GitHubデスクトップにて**メインブランチを消去**という暴挙をおかしてしまい、途方に暮れてしまいました。それを機にGitについて改めて勉強したので、アウトプット。
　もしかしたら間違えているところもあるかもしれませんが、コメントで教えていただけると幸いです。

# Gitとはバージョン管理ツールである
　そもそもGitとは何かという根本的なことさえ頭に入ってなかったのですが、Gitはバージョン管理ツールのことです。

## バージョン管理ツールのない世界を仮定する
AさんとBさんが共同であるアプリを作成した。ところが、修正箇所が見つかったので、Aさんが「アプリX」の名前を「アプリX　改訂版」として保存した。そして、このデータをBさんと共有した。するとまた修正したい箇所が見つかったので、Bさんはアプリを修正後、「アプリX　改訂版」という名前を、「アプリX　最新版」として保存した。かくしてAさんとBさんはこのようにアプリの修正を繰り返した結果、どれが最も最新版なのかわからなくなってしまった。
　まあこれは極端な例ですが、例えばアプリを修正するたびに日付を追記するとか、工夫すればこの程度はクリアできそうですよね。ただ、**時には逆もしたい**わけです。修正したものの、やはり元に戻したい。でも、どのファイル名がどこまで修正したものかわかりづらい。こういうことはありそうですね。これが少人数での開発ならまだなんとかなるかもしれませんが、開発規模が大きくなるとそうはいきませんね。
　また、**同時に作業できない**という欠点もあります。Aさんが問い合わせフォームを作っている間にBさんがトップページをつくる、といったことができないわけです。これではチームで開発する意義が薄いですし、非常に時間がかかります。なんとか同時に作業して、**今までのアプリとの変更点の差分だけ取り出せないか**ということでバージョン管理ツールが輝くわけです。



![スクリーンショット 2022-11-27 23.16.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884270/08df8092-3592-c498-9f9a-a0d07d7f4890.png)

## バージョン管理ツールがある世界
　かくしてバージョン管理ツールが使われることになるのですが、バージョン管理ツールの一つが**Git**です。（GitとGitHubは別物です。それも今になって知りました・・・）
　Gitを使う際、**母体となるデータはサーバに保存します。**　そして母体のデータを自分のPCに落とし込み、作業をするわけですね。**git clone**がそれに相当します。AさんもBさんもgit cloneしてそれぞれ作業をします。この時点でサーバではなくローカル環境で作業をすることになりますね。そして一定の作業が終わったとき、**git add**をします。そして**git commit**をすることで変更を保存します。（じゃあgit addとcommitってほぼ一緒じゃんと最初私は思ったのですが、もちろん違います。がここでは割愛します）。commitした内容、つまり変更点を母体に伝えることを、**git push**といいます。変更点を押し出す！というイメージですかね。この時点で母体のデータには変更点が保存されることになります。そこでAさんはBさんに言うわけです。「Gitにpushしたよ」と。BさんはAさんによる変更点を自分のパソコンにも反映させたいと思いますよね。それが**git pull**です。変更点を引いてくる！ということでしょうか。変更点をpushしたりpullできるということは、差分を保存しているということですから、いつ、何を変更したか確認できますし、必要なら過去にも遡ることができるわけです。

![スクリーンショット 2022-11-27 23.27.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884270/87e18399-c988-7d28-bbc5-bc03a3eef463.png)
![スクリーンショット 2022-11-27 23.36.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884270/543aeb9a-763e-1ece-832c-2305b0e0cd8b.png)

　さて、ここで疑問。**マージとかプルリクって何？** ってことです。またAさんとBさんが作業していると仮定しましょう。ところがBさんはおっちょこちょいで、ついAさんの作成したお問合せフォームを消してpushしてしまったのです。そうすると困りますよね。いくら遡れるといっても毎回のようにおっちょこちょいを発動されてはたまったもんじゃありません。そこでAさんはBさんに言いました。「pushする前に確認させて！」ここでBさんが行うのが**pull request** 、プルリクです。「他の人がpullしてもいい状態にしますね、いいですか？」というお伺いをたてるわけです。そこでAさんが「よっしゃ、大丈夫やで」となって初めて**merge**　できます。責任者が変更点を確認してmergeすることで、母体のデータがめちゃくちゃになるのを防ぎます。

# まだまだ深いよ、Gitの世界
　長くなってきたので一旦書くのをやめますが、今回は２人での作業を仮定して書いています。これが大規模なプロジェクトになったり、クライアント目線で安全を担保したりするには、今書いていることだけでは到底実現できません。だからこそ先人の方や最前線に立つエンジニアの方が素晴らしいアイデアや技術を生み出し、それを私たち一般人が（まだまだ使いこなせていませんが）享受できているのですね。
　アプリ製作を行なっていると、つい「動くと面白い！」が先行してしまい、原理原則や周辺知識が疎かになってしまっていました。これからは本質をつかむということを意識して学習していきたいと思います。それが自分の力になると信じています。
[Tabular Editor 2 Docs] ワークスペース・データベースの紹介

# Tabular Editor 2 Docs

こちらはTabular Editor 2 Docs Advent Calendar 2022への投稿記事です。

https://qiita.com/advent-calendar/2022/tabulareditor2docs2022

2022年11月下旬ごろのDocsを日本語訳しています。
最新情報は公式ページ・公式リポジトリをご確認ください。

https://tabulareditor.com/

https://github.com/TabularEditor/TabularEditorDocs

# ワークスペース・データベースの紹介

Tabular Editor 3.0は、Analysis Servicesのインスタンスに展開されたデータベースへの同時接続で、ディスクからロードされたモデルのメタデータの編集をサポートします。このデータベースを_workspace database_と呼びます。今後、Tabular Editorでタブラーモデリングを行う場合は、この方法を推奨します。

Save (Ctrl+S) を1回押すだけで、ディスクへの変更の保存とワークスペースデータベースのメタデータの更新を同時に行うことができるため、開発ワークフローが非常にシンプルになります。また、Analysis Servicesから返されたエラーメッセージは、Saveを押すとすぐにTabular Editorに表示されるという利点もあります。ある意味、ワークスペース・データベースが更新されるタイミングをコントロールできることを除けば、SSDT / Visual StudioまたはPower BI Desktopが行う方法に似ています。

Model.bimファイルやフォルダー構造からモデルを読み込むと、次のようなプロンプトが表示されます。

![image](https://user-images.githubusercontent.com/8976200/58166683-a65db180-7c8a-11e9-9df3-be9a716b3ad1.png)

* **Yes**: モデルメタデータはディスクからロードされ、すぐにAnalysis Servicesのインスタンスにデプロイされます。その後、Tabular Editorは新しくデプロイされたデータベースに接続します。次に同じモデルをディスクからロードすると、Tabular Editorは自動的に再デプロイされ、データベースに接続されます。
* **No**: モデルのメタデータは、Analysis Servicesのインスタンスに接続することなく、通常通りディスクからTabular Editorに読み込まれます。
* **No, don't ask again**: 上記のオプションと同じですが、Tabular Editorは次に同じモデルをロードしたときに再度質問することはありません。

## ワークスペース・データベースのセットアップ

上記のプロンプトで「Yes」オプションを選択すると、Analysis Servicesのインスタンスに対するサーバ名と（オプションの）資格情報の入力を求められます。OK "を押すと、インスタンス上にすでにあるデータベースのリストが表示されます。Tabular Editorは新しいデータベースをデプロイすることを想定しており、Windowsユーザー名と現在の日付と時刻に基づいて新しいデータベースのデフォルト名を提供します。

![image](https://user-images.githubusercontent.com/8976200/58179509-a10f5f80-7ca8-11e9-9764-4cb76b9d1a8b.png)

既存のデータベースをワークスペースのデータベースとして使用する場合は、リストで選択するだけです。**注意警告: 既存のデータベースを選択した場合、ディスクから読み込まれたモデルのメタデータで上書きされます。このため、本番インスタンスにワークスペース・データベースをセットアップすることは推奨されません！**。

## ユーザーオプションファイル(.tmuo)

ファイルシステム内の各モデルのワークスペース設定を追跡するために、Tabular Editor 3.0では.tmuo（Tabular Model User Optionsの略）タイプの新しいファイルを導入し、Model.bimまたはDatabase.jsonファイルの隣に配置されます。

.tmuoファイルは、以下の内容を持つ単なるjson文書です。

```json
{
  "UseWorkspace": true,
  "WorkspaceConnection": "Data Provider=MSOLAP;Data Source=localhost",
  "WorkspaceDatabase": "AdventureWorks_WS_Feature123"
}
```

ディスクからモデルのメタデータをロードする際、Tabular Editorはロードされたモデルファイルと同じディレクトリに .tmuoファイルがあるかどうかを調べます。.tmuoファイルの名前は次のパターンにしたがっている必要があります。

```
<modelfilename>.<windowsusername>.tmuo
```

このファイルにユーザー名が含まれているのは、複数の開発者が並行して開発するワークフローにおいて、お互いのワークスペース・データベースを不注意に上書きしてしまうことを防ぐためです。このファイルが存在し、ファイルの "UseWorkspace" フラグが "true" に設定されている場合、Tabular Editorはディスクからモデルをロードする際に次のステップを実行します。

1. .tmuoファイルで指定されたサーバー名とデータベース名を使用して、モデルのメタデータをワークスペース・データベースに配備します（既存のメタデータを上書きします）。
2. Connect to the newly deployed database in "workspace mode".

「ワークスペース・モード」では、Save (ctrl+s) を押すと、Tabular Editorは同時にモデルをディスクに保存し、ワークスペース・データベースを更新します。これにより、モデルのメタデータをディスクに保存する際、手動でデータベースをデプロイしたり、File > Save As... やFile > Save to Folder... を実行しなくても、新しいコードのテストやAnalysis Servicesが提供するエラーメッセージを迅速に確認することができるようになりました。
ローカルPCの環境変数にバッチファイルを登録する方法

## 準備
まずは、バッチファイルを準備します。
[※簡単なサンプルはこちら](https://github.com/sawamura-hi/batch-command)

## 登録

次に、バッチファイルのあるディレクトリパスを環境変数に登録します。

### 1.検索バー([windows]+[s])で「システムの詳細設定」を検索


### 2.詳細設定タブの環境変数をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455026/3ba0b97a-2895-c6a3-32f1-5461260b8d3d.png" width="50%">

### 3.環境変数にある「Path」をダブルクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455026/378a1637-c523-6e5c-780a-18769a6e390f.png" width="50%">

### 4.新規ボタンをクリックし、バッチファイルのあるディレクトリパスを登録する
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455026/053919c5-eebd-1560-a354-baf9b75043b6.png" width="50%">



---

以上で、ローカルPCの環境変数にバッチファイルが登録されました。

コマンドプロンプトを起動するたびに、環境変数が読み込まれ、バッチファイルが実行できます。
【Swift】Closureをasync/awaitにする

# はじめに

Closureをasync/awaitにしたく、やり方を調べてみました。

- withCheckedContinuation
- withCheckedThrowingContinuation
を使うことで実現できるようです。

# 環境
Xcode 14.0

# 内容

### ■ [withCheckedContinuation](https://developer.apple.com/documentation/swift/withcheckedcontinuation(function:_:))

```swift
func withCheckedContinuation<T>(
    function: String = #function,
    _ body: (CheckedContinuation<T, Never>) -> Void
) async -> T
```

👇のように使う

```swift
func hoge() async -> String {
    await withCheckedContinuation({ continuation in
        // ここでClosureの処理
        // 最後にcontinuation.resume()をして結果を返す
    })
}
```


### ■ [withCheckedThrowingContinuation](https://developer.apple.com/documentation/swift/withcheckedthrowingcontinuation(function:_:))
```swift
func withCheckedThrowingContinuation<T>(
    function: String = #function,
    _ body: (CheckedContinuation<T, Error>) -> Void
) async throws -> T
```

👇のように使う

```swift
func hoge() async throws -> String {
    try await withCheckedContinuation({ continuation in
        // ここでClosureの処理をする
        // 最後にcontinuation.resume()をして結果を返す
    })
}
```

### ■ [CheckedContinuation](https://developer.apple.com/documentation/swift/checkedcontinuation)
```swift
struct CheckedContinuation<T, E> where E : Error
```

- [resume(returning:)](https://developer.apple.com/documentation/swift/checkedcontinuation/resume(returning:))
`func resume(returning value: T)`
継続待ちのタスクを中断点から正常に復帰させることで再開させる
- [resume(throwing:)](https://developer.apple.com/documentation/swift/checkedcontinuation/resume(throwing:))
`func resume(throwing error: E)`
継続待ちのタスクに中断点からエラーを投げさせて再開させる
- [resume(with:)](https://developer.apple.com/documentation/swift/checkedcontinuation/resume(with:)-3gh60)
`func resume(with result: Result<T, E>)`
与えられたResult値の状態に応じて、正常に戻るかエラーを投げるかして継続待ちのタスクを再開させる

# さいごに
とても簡単でしたが、`async/await`に対応するライブラリも増えてきて使う機会は減ってきそうですね。

# 参考

https://developer.apple.com/documentation/swift/withcheckedcontinuation(function:_:)

https://developer.apple.com/documentation/swift/withcheckedthrowingcontinuation(function:_:)
[Tabular Editor 2 Docs] ビデオチュートリアル

# Tabular Editor 2 Docs

こちらはTabular Editor 2 Docs Advent Calendar 2022への投稿記事です。

https://qiita.com/advent-calendar/2022/tabulareditor2docs2022

2022年11月下旬ごろのDocsを日本語訳しています。
最新情報は公式ページ・公式リポジトリをご確認ください。

https://tabulareditor.com/

https://github.com/TabularEditor/TabularEditorDocs

# ビデオチュートリアル

[PowerBI.Tips](https://powerbi.tips/about/)とのコラボレーションにより、Daniel OtykierがTabular Editor Programに関連した4時間のトレーニングを実施します。以下のビデオで、このツールの詳細と、日常の業務での使い方をご覧ください。

ウェビナートピックス

* Tabular Editorの紹介
* スクリプトの使用
* ベストプラクティス・アナライザーでデータモデルを見直す
* Azure DevOpsによるモデルのデプロイメント

## Tabular Editorの紹介

[![Intro to Tabular Editor](http://img.youtube.com/vi/c-jZMzsvKnM/0.jpg)](http://www.youtube.com/watch?v=c-jZMzsvKnM "Intro To Tabular Editor")

## スクリプトの使用

[![Intro to Tabular Editor](http://img.youtube.com/vi/EHs5r3XCkO8/0.jpg)](http://www.youtube.com/watch?v=EHs5r3XCkO8 "Intro To Tabular Editor")

## ベストプラクティス・アナライザーでデータモデルを見直す

[![Intro to Tabular Editor](http://img.youtube.com/vi/5WnN0NG2nBk/0.jpg)](http://www.youtube.com/watch?v=5WnN0NG2nBk "Intro To Tabular Editor")

## Azure DevOpsによるモデルのデプロイメント

[![Intro to Tabular Editor](http://img.youtube.com/vi/fzZgXe3MjhI/0.jpg)](http://www.youtube.com/watch?v=fzZgXe3MjhI "Intro To Tabular Editor")

Special thanks to PowerBI.Tips for setting up these free webinars.  
Visit PowerBI.tips on YouTube - https://www.youtube.com/powerbitips  
Visit PowerBI.tips - https://powerbi.tips
JSON整形・圧縮ツールを作ってみた

# 背景
JSONテキストを扱うときに自分用のツールが欲しかったので作ってみた。

VSCodeでは、ショートカットキーや右クリックでフォーマット（整形）ができても、圧縮は提供されていなくて（もしあったら知りたい）正規表現で元の整形に直すのが面倒くさかったり、ちょっとしたテストデータを作ってコードに仕込むとき用にエスケープ処理がしたかったので、自分で作ってしまおうと思った。

# できあがったもの
https://ttokage9988.github.io/json-minify-and-formatter/

ツール名は「23日の金曜日」です。
某スプラッター映画とは全く関係ありません。

# 主な使用言語
* JavaScript
（ライブラリは使用せず）

# 機能要件
* JSON整形
    * 改行とスペースで整形
    * インデントは半角スペース４つ
* JSON1行圧縮
* JSON1行圧縮　+　エスケープ処理

# ソースコード

↓今思ったけどリファクタリングはしてない（笑）追記2022/12/04

```js
//1行圧縮
function oneline() {
    var jsonText = document.getElementById('ta-input-text');
    var s = jsonText.value.replace(/[ \t\r\n\\]/g, ""); //スペース、タブ、改行CRLFを取り除く
    var textArea = document.getElementById('ta-input-text');
    textArea.value = s;
}

//整形
function format() {
    var jsonText = document.getElementById('ta-input-text');
    if (jsonText == null) return;
    var s = jsonText.value.replace(/[ \t\r\n\\]/g, ""); //スペース、タブ、改行CRLFを取り除く
    var json = JSON.parse(s); //一旦JSのオブジェクトに変換
    var textArea = document.getElementById('ta-input-text');
    textArea.value = JSON.stringify(json, null, "    "); //整形して文字列で返す
}

// 1行圧縮してエスケープ
function onelineEscape() {
    var jsonText = document.getElementById('ta-input-text');
    var s = jsonText.value.replace(/[ \t\r\n\\]/g, "") //スペース、タブ、改行CRLFを取り除く
        .replace(/[\"]/g, "\\\""); //「"」があったらエスケープする
    var textArea = document.getElementById('ta-input-text');
    textArea.value = s;
}
```


# 実行結果

```json
//整形
{
	"member": [
		{
			"id": "1",
            "name": "山田太郎",
		},
		{
			"id": "2",
            "name": "山田花子",
		},
		{
			"id": "3",
			"name": "ドラゴン",
		}
	]
}

//1行圧縮
{"member":[{"id":"1","name":"山田太郎",},{"id":"2","name":"山田花子",},{"id":"3","name":"ドラゴン",}]}

//1行圧縮（エスケープ処理）
{\"member\":[{\"id\":\"1\",\"name\":\"山田太郎\",},{\"id\":\"2\",\"name\":\"山田花子\",},{\"id\":\"3\",\"name\":\"ドラゴン\",}]}
```

できた。
[Tabular Editor 2 Docs] SQL Server 2017への対応

# Tabular Editor 2 Docs

こちらはTabular Editor 2 Docs Advent Calendar 2022への投稿記事です。

https://qiita.com/advent-calendar/2022/tabulareditor2docs2022

2022年11月下旬ごろのDocsを日本語訳しています。
最新情報は公式ページ・公式リポジトリをご確認ください。

https://tabulareditor.com/

https://github.com/TabularEditor/TabularEditorDocs

# SQL Server 2017への対応

バージョン2.3から、Tabular EditorはSQL Server 2017 (Compatibility Level 1400)もサポートするようになりました。これは、Tabular EditorのUIが、[こちら](https://blogs.msdn.microsoft.com/analysisservices/2017/04/19/whats-new-in-sql-server-2017-ctp-2-0-for-analysis-services/) で説明されている新機能の一部を公開することを意味します。

ただし、これらの機能を使用するには、[Tabular Editor の適切なビルド](https://github.com/otykier/TabularEditor/releases/tag/2.5-CL1400) をダウンロードする必要があることに注意してください。これは、SQL Server 2017 / SSDT 17.0向けに新しいクライアントライブラリのセットがMicrosoftから提供されており、これらのライブラリはTabular EditorのSQL Server 2016-ビルドと互換性がないためです。新しいライブラリは、新しい[SSDTのバージョン](https://docs.microsoft.com/en-us/sql/ssdt/download-sql-server-data-tools-ssdt)から取得できます（Visual Studio 2015が必要です）。

互換性レベル1400の機能が必要ない場合は、SQL Server 2016-ビルドの[Tabular Editor](https://github.com/otykier/TabularEditor/releases/tag/2.5)を使用できます。

ここでは、Tabular Editorで新機能がどのように使用されるかを簡単に説明します。

## 日付リレーションシップ

すべてのリレーションシップで、プロパティ・グリッドの「Join on Date Behavior」プロパティが公開されるようになりました。

![image](https://cloud.githubusercontent.com/assets/8976200/25297821/9dd46be0-26f0-11e7-92bf-10a921ed20dc.png)

## バリエーション（列・階層再利用）

プロパティグリッドの「バリエーション」プロパティを展開することで、カラムにバリエーションを設定できます。

![image](https://cloud.githubusercontent.com/assets/8976200/25297845/c69ecc5a-26f0-11e7-93af-b7a2a0cc9310.png)

なお、**Object Level Security** はカラムレベルで指定することも可能です。

省略記号ボタンをクリックすると、バリエーションコレクションエディターが開き、ここからPower BIで列や階層を再浮上させる方法を設定できます。

![image](https://cloud.githubusercontent.com/assets/8976200/25297884/fd4faf58-26f0-11e7-9a1a-df7a1b05f663.png)

テーブルレベルで「バリエーションとしてのみ表示」プロパティを「True」に設定することを忘れないでください。

![image](https://cloud.githubusercontent.com/assets/8976200/25297917/2c1e4b64-26f1-11e7-8ce6-a62aef2b7d8a.png)

**詳細行式**は、テーブルおよびメジャーに直接設定できます。ただし、現時点では、構文の強調表示やインテリセンスは使用できません。

Hierarchyオブジェクトは、ラグドヒエラルキーに便利な新しい**Hide Members**プロパティを公開します。
[Tabular Editor 2 Docs] Power BI Desktopとの連携

# Tabular Editor 2 Docs

こちらはTabular Editor 2 Docs Advent Calendar 2022への投稿記事です。

https://qiita.com/advent-calendar/2022/tabulareditor2docs2022

2022年11月下旬ごろのDocsを日本語訳しています。
最新情報は公式ページ・公式リポジトリをご確認ください。

https://tabulareditor.com/

https://github.com/TabularEditor/TabularEditorDocs

# Power BIデスクトップとの連携

2020年7月現在、[Power BI Desktop は External Tools のサポートを追加します](https://docs.microsoft.com/da-dk/power-bi/create-reports/desktop-external-tools)。これにより、DesktopでImportedまたはDirectQueryデータを扱う際に、Tabular Editorで特定のモデリング操作を実行できるようになります。

![image](https://user-images.githubusercontent.com/8976200/87296924-dcea3180-c507-11ea-9cf9-2f647d26a2a9.png)

## 前提条件

- 2020年7月版[Power BI Desktop](https://www.microsoft.com/en-us/download/details.aspx?id=58494) (またはそれ以降）
- [最新版 Tabular Editor](https://github.com/otykier/TabularEditor/releases/latest)
- Power BI Desktopのプレビュー機能で [Enhanced Metadata](https://docs.microsoft.com/en-us/power-bi/connect-data/desktop-enhanced-dataset-metadata) を有効化する。

また、[automatic date/time](https://docs.microsoft.com/en-us/power-bi/transform-model/desktop-auto-date-time) は **disabled** にすることを強く推奨します（Power BI Desktopの「データ読み込み」での設定）。

## 対応するモデリング操作

デフォルトでは、Power BI Desktopモデルに接続すると、Tabular Editorは限られた数のオブジェクトとプロパティしか編集できなくなります。これらは以下の通りです。

- メジャー（任意のプロパティの追加・削除・編集）
- 計算グループと計算項目（任意のプロパティの追加/削除/編集）
- パースペクティブ（任意のプロパティの追加・削除・編集）
- 翻訳（追加・削除）
  - メタデータの変換は、モデル内のどのオブジェクトにも適用できますが、Power BI Desktopはデフォルトのモデル カルチャへの変換をまだサポートしていないことに注意してください。

**注意：** Tabular EditorのFile > Preferencesダイアログで "Allow unsupported Power BI features (experimental)" オプションを有効にすると、Tabular Editorは **any** オブジェクトとプロパティを編集できるようになり、Power BI Desktopがサポートしていないモデル変更を引き起こす可能性があり、クラッシュや破損した .pbixファイルを引き起こす可能性があるため、注意が必要です。この場合、Microsoftサポートは対応できませんので、自己責任で使用し、念のため.pbixファイルのバックアップをとっておいてください。
[Tabular Editor 2 Docs] キーボードショートカット

# Tabular Editor 2 Docs

こちらはTabular Editor 2 Docs Advent Calendar 2022への投稿記事です。

https://qiita.com/advent-calendar/2022/tabulareditor2docs2022

2022年11月下旬ごろのDocsを日本語訳しています。
最新情報は公式ページ・公式リポジトリをご確認ください。

https://tabulareditor.com/

https://github.com/TabularEditor/TabularEditorDocs

# Keyboard Shortcuts

バージョン2.7.3より、Tabular Editorは以下のキーボードショートカットをサポートするようになりました。

|General|Shortcut|
|---|---|
|New model|Ctrl+N|
|Load model from a file|Ctrl+O|
|Load model from a database|Ctrl+Shift+O|
|Save model|Ctrl+S|
|Copy selection|Ctrl+C|
|Cut selection|Ctrl+X|
|Paste|Ctrl+V|
|Undo|Ctrl+Z|
|Redo|Ctrl+Y|
|Select All|Ctrl+A|
|~Launch Deployment Wizard~|~F6~|
|Launch Best Practice Analyzer|F10|

|Expression Editor|Shortcut|
|---|---|
|Find|Ctrl+F|
|Find and replace|Ctrl+H|
|Go to definition|F12|
|Navigate back|Alt+Left arrow|
|Navigate forward|Alt+Right arrow|
|Format DAX|F6|
|Format DAX (Short lines)|Ctrl+F6|
|Comment lines|Ctrl+Shift+C|
|Uncomment lines|Ctrl+Shift+U|

|Script Editor|Shortcut|
|---|---|
|Find|Ctrl+F|
|Find and replace|Ctrl+H|
|Run script|F5|

|Explorer tree|Shortcut|
|---|---|
|Navigate up or down|Up / Down arrow|
|Expand / collapse current node|Right / Left arrow|
|Expand / collapse current node and all subnodes|Ctrl+Right / Left arrow|
|Expand / collapse entire tree|Ctrl+Shift+Right / Left arrow|
|Toggle measures|Ctrl+1|
|Toggle columns|Ctrl+2|
|Toggle hierarchies|Ctrl+3|
|Toggle display folders|Ctrl+4|
|Toggle hidden objects|Ctrl+5|
|Toggle Metadata Columns|Ctrl+F1|
|Toggle Alphabetical Ordering|Ctrl+F2|
|Toggle all object types|Ctrl+F3|
|Filter|Ctrl+F|
|Toggle filter|Ctrl+Shift+F|
|Edit Expression|Enter|
|Navigate back|Alt+Left arrow|
|Navigate forward|Alt+Right arrow|
|Show dependencies|F3|
|Make invisible|Ctrl+I|
|Make visible|Ctrl+U|
|Create new measure|Alt+1|
|Create new calculated column|Alt+2|
|Create new hierarchy|Alt+3|
|Create new data column|Alt+4|
|Create new table|Alt+5|
【Linux】sedで追加する文字列にスペースや改行をする方法

## スペースを追加する

追加する文字列にスペースを追加するには次のように実行します。  

```terminal
sed -i "/text/a \          追加するテキスト" sample.txt
```

```sample.txt
text
          追加テキスト
```

## 改行を追加する

改行を追加するには次のように実行します。  

```terminal
sed -i "/text/a 追加するテキスト\n" sample.txt
```

```sample.txt
text
追加するテキスト

          追加テキスト
```