KiCad備忘録

KiCadを使うたびに思い出すところから始まる。

バージョンは5.0.0-3。フットプリントを関連付けで左側ペインを選択しても右側ペインの絞り込みができないのはバグなんだろうか

シンボルの作成(シンボルライブラリーエディター)

  • 「ファイル」→「新規ライブラリーを作成」
  • 「シンボル」→「新規シンボル」

シンボルの追加

  • 「設定」→「シンボル ライブラリーを管理」→「ライブラリーを参照」
    • パスにKIPRJMODが使える

フットプリントの作成(フットプリントエディター)

  • 「ファイル」→「新規フットプリント」
  • 「新規ライブラリーを作成して現在のフットプリントを保存」

f:id:yskoht:20181014151738p:plain

フットプリントの追加

  • 「設定」→「フットプリント ライブラリーを管理」→「ライブラリーを参照」

自動配線

  • 「Pcbnew」→「ファイル」→「エクスポート」→「Specctra DSN」
    • 「エクスポートできません。問題点を修正してやり直してください」というそっけないダイアログが出てしまったら、どこかのリファレンスがREF**のままになっているかも

f:id:yskoht:20181014151758p:plain

ガーバーデータ出力

  • 「Pcbnew」→「ファイル」→「プロット」

8月のキーボード

8月はキーボードイベントがたくさんありました。たくさんキーボードを見て、作ったのでそのメモです。

8/4, 8/5: Maker Fair Tokyo 2018

  • 遊舎工房でアクリルキーホルダー買ったり、普通にProMicro買ったり、HelixPicoを遠くから眺めてみたり

f:id:yskoht:20180901195719j:plain
HelixPicoアクリルキーホルダー

  • TALPKEYBOARDでは結構ゆっくりお話させてもらえて、3Dプリンタで作ったキーキャップの話とか、MDFの話とか聞けてたのしかった(写真もたくさん撮らせてもらった)。展示されていたどのキーボードも質感がよくて、自分もディテールにこだわっていきたい

f:id:yskoht:20180901195845j:plain

f:id:yskoht:20180901195922j:plain

f:id:yskoht:20180901201225j:plain

  • 最後にプレゼン。プレゼン中に使っているBlockyがめっちゃかっこいい

Blocky

  • Mint60は並んだけど買えなかった。Blockyだけ買えた
  • スイッチの足が4本あるのではんだ付けが結構たいへんかもしれない
  • かわいい

f:id:yskoht:20180901204027j:plain

8/10: コミックマーケットC94 (1日目)

2つキーボードを買いに行った。キーボード作るのにも慣れてきた感があったんだけど盛大に事故った

Mint60

  • row staggeredなキーボード好き
  • 左側の下段の配列が標準的な配列よりも1u分右にずれていて、⌘キーが押しやすいなと思った
  • 間違えてスペーサを下段に2つ付けてしまって、かっこ悪い感じになってしまったのがすごい悔しい😩ビルドガイドちゃんと読むべき

f:id:yskoht:20180901200030j:plain

f:id:yskoht:20180901200108j:plain

Fortitude60

  • ミドルプレートがPCBで、アクリルが3mm。この剛健さがかなり好き
    • キーボードは頑丈でないといけない
  • USB-C最高
  • スイッチはんだ付けする際は、ケースを仮組みしておくべき😩ビルドガイドちゃんと読むべき
    • これをやっておかないとケースのアクリルがはまらなくなる場合がある1

f:id:yskoht:20180901200141j:plain

f:id:yskoht:20180901200207j:plain

8/25: Tokyo Mechanical Keyboard Meetup Vol. 5

いくつかの古いキーボードに触らせてもらえた。スイッチほんと良い

f:id:yskoht:20180901200617j:plain

f:id:yskoht:20180901200335j:plain

f:id:yskoht:20180901200417j:plain

f:id:yskoht:20180901200439j:plain

f:id:yskoht:20180901200455j:plain

f:id:yskoht:20180901200508j:plain

f:id:yskoht:20180901200524j:plain

f:id:yskoht:20180901200656j:plain

f:id:yskoht:20180901200714j:plain

f:id:yskoht:20180901200730j:plain

f:id:yskoht:20180901200746j:plain

f:id:yskoht:20180901200800j:plain

f:id:yskoht:20180901200827j:plain

f:id:yskoht:20180901200848j:plain

f:id:yskoht:20180901200914j:plain

f:id:yskoht:20180901200930j:plain

f:id:yskoht:20180901201005j:plain

f:id:yskoht:20180901201023j:plain

f:id:yskoht:20180901201041j:plain

f:id:yskoht:20180901201103j:plain

pakbd
  • 展示してたら何人かの人たちにカチカチしてもらえたり、写真撮ってもらえた

f:id:yskoht:20180901201433j:plain

f:id:yskoht:20180901201449j:plain

f:id:yskoht:20180901201506j:plain

  • 今後のやりたいこと。やるかどうか、できるかどうかは知らない
    • 基板のリファクタリング(ProMicro、スイッチ位置の修正。シルク入れ等)
    • QMKファームウェアの整備
    • 薄型化
    • LED対応
    • ホットスワップソケット対応
    • ミドルプレートの作成
      • ☁→HOKORI対策
    • ステンレスプレートの作成
      • キーボードは重くないといけない
    • tilt機構
    • 左右一体で使う場合のロック機構
      • 左右バラバラになってしまうよりも、くっつけてたほうが持ち運びやすい?
      • 左右くっつけて使う場合はTRRSケーブルなしでも動くようにしたい
    • トラックポイント
    • USB-C化
    • 静電容量無接点スイッチ対応
    • ARM化、脱QMK
      • ぺかそさんがプレゼンで言っていたのでそれに期待
    • Bluethooth化

  1. 無理矢理はめ込もうとするとケースが割れたキーボードを使うことになる。普通にスプリットキーボードを使っているだけでもキーボード割れてるとか揶揄されるのに

mac 環境構築メモ

OS

環境設定

アプリ

画像からQuineを生成するGemを作った

AAQ - Ascii Art Quine

できること

画像からRubyQuineをつくれます。たとえば、Octocatの画像をQuineにしてみます。

f:id:yskoht:20180721224507p:plain
Octcat

出力されるアスキーアートは自分自身を出力するRubyのプログラムになっています。

f:id:yskoht:20180721231717g:plain

aaq Octocat.png | tee OctocatQuine.rb
ruby OctocatQuine.rb

--colorオプションを付けるとカラフルになります。これもQuineになっているので、エスケープシーケンスを取り除けばRubyで実行できます。

f:id:yskoht:20180721234346g:plain

ruby OctocatQuine.rb --color
ruby OctocatQuine.rb --color | ruby -ne 'puts $_.gsub(/\e.*?m/, "")'  | ruby  #  エスケープシーケンスを除いて実行

インストール

以下の環境で動作確認しています。

rmagickを使っているので、 ImageMagickを先にインストールしておきます。 ImageMagickのバージョン7を入れてしまうと、rmagickのインストール時にエラー1が出てしまうので、バージョン6をインストールします。

brew install imagemagick@6
echo 'export PATH="/usr/local/opt/imagemagick@6/bin:${PATH}"' >> ~/.bash_profile
echo 'export PKG_CONFIG_PATH="/usr/local/opt/imagemagick@6/lib/pkgconfig:${PKG_CONFIG_PATH}"' >> ~/.bash_profile

gemでaaqをインストールします。

gem install aaq

動作確認します。

$ aaq -v
aaq 0.1.2

Enjoy!

参考

Quineの作り方

gifはasciinemaasciicast2gifを使いました。

asciinema rec screen.cast
docker run --rm -v $PWD:/data asciinema/asciicast2gif -s 1.8 -t monokai screen.cast screen.gif

Gemの公開方法

色のエスケープシーケンス

Ubuntu 18.04 環境構築メモ

インストールを3回やるはめになったのでメモ。

インストール

設定

  • 背景
  • Dock
    • アイコンサイズ
  • 地域と言語
    • English
  • ユニバーサルアクセス
    • カーソル点滅OFF
  • 電源
    • ブランクスクリーン

CapsLockをCtrlにする

gsettings set org.gnome.desktop.input-sources xkb-options "['ctrl:nocaps']"

linuxbrew

Linuxbrew | The Homebrew package manager for Linux

sudo gem install activesupport plist backports
sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"

test -d ~/.linuxbrew && eval $(~/.linuxbrew/bin/brew shellenv)
test -d /home/linuxbrew/.linuxbrew && eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
test -r ~/.bash_profile && echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.bash_profile
echo "eval \$($(brew --prefix)/bin/brew shellenv)" >>~/.profile

apt

sudo apt install -y vim emacs tmux screen git curl 
sudo apt install -y build-essential gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev zlib1g-dev

deb

sudo dpkg -i *.deb

Dotfiles

git clone https://github.com/yskoht/dotfiles.git ~/dotfiles
cd dotfiles
make install setup

Python

git clone https://github.com/pyenv/pyenv.git ~/.pyenv
git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv
pyenv install 3.6.5
pyenv global 3.6.5
pip install --upgrade pip

Ruby

sudo apt install -y rbenv ruby-build
git clone https://github.com/jf/rbenv-gemset.git $HOME/.rbenv/plugins/rbenv-gemset
rbenv install 2.4.1
rbenv global 2.4.1

Node.js

sudo apt install -y nodejs npm

fish

sudo apt-add-repository ppa:fish-shell/release-2
sudo apt-get update
sudo apt-get -y install fish
sudo apt install -y peco
curl -Lo ~/.config/fish/functions/fisher.fish --create-dirs git.io/fisherman
chsh
fisher z
fisher 0rax/fish-bd
fisher oh-my-fish/plugin-peco
fisher simnalamburt/shellder

powerline font

git clone https://github.com/powerline/fonts.git
./fonts/install.sh

fcitx

sudo apt install -y fcitx-mozc
sudo apt remove -y ibus

Javascriptを調べたときのメモ

ES2015, ES2016, ES2017

Promise, async/await

Tutorial: Intro To Reactをやったメモ

追加課題のメモです。初心者です。

1. Display the location for each move in the format (col, row) in the move history list.

@@ -49,6 +49,8 @@ class Game extends React.Component {
     this.state = {
       history: [{
         squares: Array(9).fill(null),
+        col: null,
+        row: null,
       }],
       stepNumber: 0,
       xIsNext: true,
@@ -66,6 +68,8 @@ class Game extends React.Component {
     this.setState({
       history: history.concat([{
         squares: squares,
+        col: (i % 3) + 1,
+        row: Math.floor(i / 3) + 1,
       }]),
       stepNumber: history.length,
       xIsNext: !this.state.xIsNext,
@@ -86,7 +90,7 @@ class Game extends React.Component {
 
     const moves = history.map((step, move) => {
       const desc = move ?
-        'Go to move #' + move :
+        'Go to move #' + move + ' (' + step.col + ',' + step.row + ')' :
         'Go to game start';
       return (
         <li key={move}>

状態にcolrowを持つように変更。

2. Bold the currently selected item in the move list.

index.js

@@ -92,9 +92,10 @@ class Game extends React.Component {
       const desc = move ?
         'Go to move #' + move + ' (' + step.col + ',' + step.row + ')' :
         'Go to game start';
+      const textStyle = (move === this.state.stepNumber) ? 'bold'  : null;
       return (
         <li key={move}>
-          <button onClick={() => this.jumpTo(move)}>{desc}</button>
+          <button className={textStyle} onClick={() => this.jumpTo(move)}>{desc}</button>
         </li>
       );
     });

style.css

@@ -48,3 +48,7 @@ ol, ul {
 .game-info {
   margin-left: 20px;
 }
+
+.bold {
+  font-weight: bold;
+}

classNameを切り替え。

3. Rewrite Board to use two loops to make the squares instead of hardcoding them.

@@ -16,30 +16,21 @@ class Board extends React.Component {
       <Square
         value={this.props.squares[i]}
         onClick={() => this.props.onClick(i)}
+        key={i}
       />
     );
   }
 
   render() {
-    return (
-      <div>
-        <div className="board-row">
-          {this.renderSquare(0)}
-          {this.renderSquare(1)}
-          {this.renderSquare(2)}
-        </div>
-        <div className="board-row">
-          {this.renderSquare(3)}
-          {this.renderSquare(4)}
-          {this.renderSquare(5)}
-        </div>
-        <div className="board-row">
-          {this.renderSquare(6)}
-          {this.renderSquare(7)}
-          {this.renderSquare(8)}
-        </div>
-      </div>
-    );
+    let squares = [];
+    for(let row = 0; row < 3; row++) {
+      let rows = [];
+      for(let col = 0; col < 3; col++) {
+        rows.push(this.renderSquare(row*3 + col));
+      }
+      squares.push(<div className="board-row" key={row}>{rows}</div>);
+    }
+    return (<div>{squares}</div>);
   }
 }

keyを追加。

4. Add a toggle button that lets you sort the moves in either ascending or descending order.

@@ -45,6 +45,7 @@ class Game extends React.Component {
       }],
       stepNumber: 0,
       xIsNext: true,
+      isDescendingOrder: false,
     };
   }
 
@@ -74,12 +75,18 @@ class Game extends React.Component {
     });
   }
 
+  toggleOrder() {
+    this.setState({
+      isDescendingOrder: !this.state.isDescendingOrder,
+    });
+  }
+
   render() {
     const history = this.state.history;
     const current = history[this.state.stepNumber];
     const winner = calculateWinner(current.squares);
 
-    const moves = history.map((step, move) => {
+    let moves = history.map((step, move) => {
       const desc = move ?
         'Go to move #' + move + ' (' + step.col + ',' + step.row + ')' :
         'Go to game start';
@@ -90,6 +97,14 @@ class Game extends React.Component {
         </li>
       );
     });
+    let movesList;
+    if(this.state.isDescendingOrder) {
+      moves.reverse();
+      movesList = <ol reversed>{moves}</ol>;
+    }
+    else {
+      movesList = <ol>{moves}</ol>;
+    }
 
     let status;
     if(winner) {
@@ -108,7 +123,8 @@ class Game extends React.Component {
         </div>
         <div className="game-info">
           <div>{status}</div>
-          <ol>{moves}</ol>
+          <button onClick={() => this.toggleOrder()}>toggle</button>
+          {movesList}
         </div>
       </div>
     );

状態にisDescendingOrderを追加。<ol>まで逆順にする必要はなかったかもしれない。

5. When someone wins, highlight the three squares that caused the win.

index.js

@@ -3,8 +3,9 @@ import ReactDOM from 'react-dom';
 import './style.css';
 
 function Square(props) {
+  const buttonClass = props.isHighlight ? "square highlight" : "square";
   return (
-    <button className="square" onClick={props.onClick}>
+    <button className={buttonClass} onClick={props.onClick}>
       {props.value}
     </button>
   );
@@ -17,6 +18,7 @@ class Board extends React.Component {
         value={this.props.squares[i]}
         onClick={() => this.props.onClick(i)}
         key={i}
+        isHighlight={this.props.highlightLine.includes(i)}
       />
     );
   }
@@ -84,7 +86,8 @@ class Game extends React.Component {
   render() {
     const history = this.state.history;
     const current = history[this.state.stepNumber];
-    const winner = calculateWinner(current.squares);
+    const w = calculateWinner(current.squares);
+    const [winner, line] = (w) ? w : [null, [null]];
 
     let moves = history.map((step, move) => {
       const desc = move ?
@@ -119,6 +122,7 @@ class Game extends React.Component {
           <Board 
             squares={current.squares}
             onClick={(i) => this.handleClick(i)}
+            highlightLine={line}
           />
         </div>
         <div className="game-info">
@@ -152,7 +156,7 @@ function calculateWinner(squares) {
   for(let i = 0; i < lines.length; i++) {
     const [a, b, c] = lines[i];
     if(squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
-      return squares[a];
+      return [squares[a], lines[i]];
     }
   }
   return null;

style.css

@@ -40,6 +40,10 @@ ol, ul {
   background: #ddd;
 }
 
+.highlight {
+  color: #ff0000;
+}
+
 .game {
   display: flex;
   flex-direction: row;

calculateWinnerでハイライトするラインを返すように修正。そのラインをBoardpropsに渡す。squareの添字がラインに含まれていたらハイライトするようにhighlightclassNameに追加する。

6. When no one wins, display a message about the result being a draw.

@@ -113,7 +113,11 @@ class Game extends React.Component {
     if(winner) {
       status = 'Winner: ' + winner;
     } else {
-      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
+      if(this.state.stepNumber === 9) {
+        status = 'Draw';
+      } else {
+        status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
+      }
     }
 
     return (

あれ、なんかこれ簡単じゃね?と思って書いたけど、これだと全てのマスが埋まった時にDrawと表示されるだけなので、"When no one wins,"じゃない。

@@ -55,7 +55,9 @@ class Game extends React.Component {
     const history = this.state.history.slice(0, this.state.stepNumber + 1);
     const current = history[history.length - 1];
     const squares = current.squares.slice();
-    if(calculateWinner(squares) || squares[i]) {
+    if(calculateWinner(squares) ||
+       squares[i] ||
+       isDraw(squares, this.state.xIsNext)) {
       return;
     }
     squares[i] = this.state.xIsNext ? 'X' : 'O';
@@ -113,7 +115,11 @@ class Game extends React.Component {
     if(winner) {
       status = 'Winner: ' + winner;
     } else {
-      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
+      if(isDraw(current.squares, this.state.xIsNext)) {
+        status = 'Draw';
+      } else {
+        status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
+      }
     }
 
     return (
@@ -160,4 +166,19 @@ function calculateWinner(squares) {
     }
   }
   return null;
-} 
+}
+
+function isDraw(squares, xIsNext) {
+  if(calculateWinner(squares)) {
+    return false;
+  }
+
+  for(let i = 0; i < squares.length; i++) {
+    if(squares[i] === null) {
+      let sqrs = squares.slice();
+      sqrs[i] = xIsNext ? 'X' : 'O';
+      if(isDraw(sqrs, !xIsNext) === false) return false;
+    }
+  }
+  return true;
+}

isDraw()を追加。引き分けの時にtrue, それ以外(どちらかが勝てるパターンが残っている場合)はfalseを返す。

全探索でざっくり512パターン。イミュータブルが大事だよ、と書かれていたのでslice()してるけど、計算量とかメモリってどのくらいまでなら許容されるのかなぁ。