Riot.jsで数字のランダム選択

背景

会社内でコンペみたいな発表会があったのですが、ランダムにチーム番号を選ぶ要件がありました。
フリーソフトを利用していたのですが、広告が頻繁に表示されうざそうだったので作ってみた。

完成品

こんな感じで出来ました。

名称未設定.mov.gif

完成品は下記。
http://game.hasito.com:3001/num.random/

開発

要件

要件としては、ランダムに発表者を選択したい場合に、事前ではなくその場で選択したい。このとき、基本的には同一の番号は選択されないものとする。的な感じ。
また、可能であれば選択したが後半に発表者を回したい要件参加予定の番号だったが参加できなくなったため、選択済みとしたい要件等も網羅できればなお良い。

仕様

下記のような仕様を有する。

番号数の決定

最初に数値を入力可能で、この数値に応じて**連続する数(選択可能な数字)**を生成する。
例えば、100であれば0~99までを生成する。

ランダムな選択

ユーザが任意のタイミングで、クリックなどの動作により生成された選択可能な数字からランダムに1つ選択できる。
また、この時に1度選択されたもの無効化されているものは選択されない。

数字の無効化

ユーザは任意のタイミングで生成されたリストから任意の数字を無効化できる。
無効化された数字はランダムに選択されない。

数字の有効化

ユーザは任意のタイミングで生成されたリストから任意の数字を有効化できる。
有効化された数字はランダムに選択される。

コーディング

今回の肝はjavascriptのオブジェクトの参照関連というイメージでした。
最初にランダムな数字を持った配列と同一のオブジェクトを参照するランダムな配列を生成して、それを介してオブジェクトを変化させる。
主たるコードは下記です。

  
var self     = this;  
self.shuffle = false;  
self.list    = false;  
self.now     = "Click!"  
self.msg     = ""  
// ランダム選択開始関数  
start(e){  
    if(_chk(e.target.value).e){  
        // こちらが正規な順(1,2,3...)で並んでいるオブジェクトリスト  
        self.list    = [...Array(e.target.value*1)].map((v,i)=>{return {idx:i,st:true}});  
        // こちらがランダムな順で並んでいるオブジェクトリスト  
        // ただし、中身は正規な順のリストと同一のオブジェクトを参照  
        self.shuffle = [...Array(e.target.value*1)].map((v,i)=>{return self.list[i];});  
        // sortで戻り値をランダムにさせてshuffleさせる  
        self.shuffle = self.shuffle.sort((a,b)=>{return (Math.random()-0.5)});  
    }  
}  
// 入力値check関数、戻り値は結果とエラー文字列  
var _chk=(v)=>{  
    if(isNaN(v)){return {e:false,msg:"数値を入力してください。"}}  
    var vv = v*1;  
    if(vv<=0){return {e:false,msg:"0より大きな数を入力してください。"}}  
    if(vv>100){return {e:false,msg:"100より小さな数を入力してください。"}}  
    return {e:true,msg:""};  
}  
// 入力チェック関数(入力されるたびに実行)  
chk(e){  
    self.msg = _chk(e.target.value).msg;  
}  
// ランダムな数字の選択関数。  
refresh(){  
    //シャッフルされているので最初から順に取得(st=falseは選択済み)  
    var _now    = self.shuffle.find(v=>{return v.st;});  
    if(_now){  
        _now.st  = false;  
        self.now = _now.idx;  
    }else{  
        self.now = "end"//選択に失敗した場合は終了  
    }  
}  
// 要素の無効化 or 有効化  
rem(e){  
    e.st=!e.st; //無効だったら有効に 有効だったら無効に  
    // 有効無効変えてもシャッフル更新しなければ毎回同じ順なので更新  
    self.shuffle = self.shuffle.sort((a,b)=>{return (Math.random()-0.5)});  
}  

完成コード

  
<test>  
<div class="bk">  
    <div if={!list}>[ランダムな数値選択アプリケーション]<br>下記に数値を入力すると、任意の数の連続する数が生成されランダムに選択する事が可能です。</div>  
    <div if={!list} class="input-bk"><input oninput={chk} onchange={start} type="text"></input></div>  
    <div if={!list}>{msg}</div>  
    <div if={list}  each={v in list} class="item {act:v.st}" onclick={rem.bind(this,v)} class="vv">{v.idx}</div>  
    <div if={list}  class="now" onclick={refresh} class="v">{now}</div>  
</div>  
<style>  
.bk{  
    text-align:center;  
    width:100vw;  
    height:100vh;  
    background-color:#fff;  
    overflow:hidden;  
}  
.input-bk{  
    cursor: pointer;  
    display:block;  
    width:55vw;  
    height:25vw;  
    border-radius:3vw;  
    overflow:hidden;  
    margin:10vh auto;  
}  
input{  
    font-size:25vw;  
    text-align:center;  
    display:block;  
    width:100%;  
    height:100%;  
    margin:0;  
    padding:10px;  
    background-color:#f00;  
    color:#fff;  
    border:none;  
    border-radius:0;  
    outline:none;  
    appearance:none;  
}  
.now{  
    cursor: pointer;  
    line-height:35vw;  
    font-size:15vw;  
    display:block;  
    width:35vw;  
    height:35vw;  
    border-radius:50%;  
    background-color:#00f;  
    color:#fff;  
    margin:10vh auto;  
}  
.item{  
    color:#fff;  
    cursor: pointer;  
    line-height:5vw;  
    font-size:3vw;  
    display:inline-block;  
    width:5vw;  
    height:5vw;  
    border-radius:50%;  
    background-color:#555;  
    margin:0.5vw;  
}  
.act{  
    background-color:#f00;  
}  
</style>  
<script>  
var self     = this;  
self.shuffle = false;  
self.list    = false;  
self.now     = "Click!"  
self.msg     = ""  
start(e){  
    if(_chk(e.target.value).e){  
        self.list    = [...Array(e.target.value*1)].map((v,i)=>{return {idx:i,st:true}});  
        self.shuffle = [...Array(e.target.value*1)].map((v,i)=>{return self.list[i];});  
        self.shuffle = self.shuffle.sort((a,b)=>{return (Math.random()-0.5)});  
    }  
}  
var _chk=(v)=>{  
    if(isNaN(v)){return {e:false,msg:"数値を入力してください。"}}  
    var vv = v*1;  
    if(vv<=0){return {e:false,msg:"0より大きな数を入力してください。"}}  
    if(vv>100){return {e:false,msg:"100より小さな数を入力してください。"}}  
    return {e:true,msg:""};  
}  
chk(e){  
    self.msg = _chk(e.target.value).msg;  
}  
refresh(){  
    var _now    = self.shuffle.find(v=>{return v.st;});  
    if(_now){  
        _now.st  = false;  
        self.now = _now.idx;  
    }else{  
        self.now = "end"  
    }  
}  
rem(e){  
    e.st=!e.st;  
    self.shuffle = self.shuffle.sort((a,b)=>{return (Math.random()-0.5)});  
}  
</script>  
</test>  
  

最後に

もう少しアニメーションとかつけたかった…
今度、時間があればやろうかな…

Reactで作る「令和」パズル

#背景
仕事で使うので、Reactの勉強がてらパズルを作ってみた。
話題の「令和」と「平成」を使ったやつ…(すでにちょっと遅い感じも…)

#完成品
下記のようなものができました。
スタートを押すと開始され、「令和」で揃えると完了!

See the Pen reiwa puzzle by hashito (@hashito) on CodePen.

###TODO(残課題)

  • ウィンドウを小さくすると正しく表示されない
  • HTMLからの定義をもらってlevelやら大きさを可変させたい
  • もう少し…コードを整理したい

#詰まった所
##thisstateが参照できない。
下記のようなコードで何度確認してもthis.stateが定義されていない!

class Puzzle extends React.Component {  
  constructor(props) {  
    super(props);  
    ....  
  render() {  
    return (  
      <span  
        className="puzzle"  
        cal={this.state.y}  

###解決
コンストラクタでthis.render=this.render.bind(this);がされていない…
はい、ドキュメントを読みましょうってことですね。

class Puzzle extends React.Component {  
  constructor(props) {  
    super(props);  
    this.render=this.render.bind(this);  
    ....  
  render() {  
    return (  
      <span  
        className="puzzle"  
        cal={this.state.y}  

##renderが呼び出されない
コンストラクタで受け取ったpropsを下記のようにstateに直接引き渡しをしていた。
コンストラクタはインスタンス生成時にしか呼び出されなかった…

class Puzzle extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state= props;  
    ....  
  render() {  
    return (  
      <span  
        className="puzzle"  
        cal={this.state.y}  

下記のように改善…
しかし、更新されず…

class Puzzle extends React.Component {  
  constructor(props) {  
    super(props);  
    this.state.y {y:props.y};  
    ....  
  render() {  
    return (  
      <span  
        className="puzzle"  
        cal={this.state.y}  

###解決
純粋にそのままpropsを見ればよかったのだ…

class Puzzle extends React.Component {  
  constructor(props) {  
    super(props);  
    ....  
  render() {  
    return (  
      <span  
        className="puzzle"  
        cal={this.props.y}  

#感想
Reactは結構「こうしてください!」ってのが多い感じがした。
書き方やロジックが矯正されるので誰が書いても同じようなコードになるのが利点なのかな…
オブジェクト構成とかも…

nodejs aws-sdkでs3ファイルアップロード

#背景
node.jsでaws-sdkを利用してファイルのアップロードしようと思ったけど古い記事が多かったのでまとめさせていただきます。
正規なやつは下記を参照…
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html

#最初に
下記の項目は飛ばさせていただきます…

  1. node.jsやらnpmやらのインストール
  2. awsのアカウント作成
  3. awsのs3のバケット作成

#やり方
##aws-sdkのインストール

 npm init  
 npm install --save aws-sdk fs  

##アクセスキーの取得
AWSの画面の右上の方の「アカウント名」をクリック>「セキュリティ認証情報」を選択
スクリーンショット 2017-10-22 21.27.28.png

アクセスキーの項目で「新しいアクセスキーの作成」をクリックして作成
スクリーンショット 2017-10-22 21.27.48.png

下記のようなファイルがダウンロード出来ます。

AWSAccessKeyId=xxxxxxxxxxxxxxxxxxxx  
AWSSecretKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  

これをこんな感じで変更して拡張子をjsonに変更

{"accessKeyId": "xxxxxxxxxxxxxxxxxxxx",  
 "secretAccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}  

##コーディング
上記のファイルをプロジェクトファイルに移動して…

var AWS = require('aws-sdk');  
var fs  = require('fs');  
  
AWS.config.loadFromPath('./rootkey.json');  
AWS.config.update({region: 'リージョン名'});  
  
var s3 = new AWS.S3();  
var params = {  
 Bucket: "バケット名",  
 Key: "アップロード後のファイル名.jpg"  
};  
var v= fs.readFileSync("./アップロード対象ファイル名.jpg");  
params.Body=v;  
s3.putObject(params, function(err, data) {  
  if (err) console.log(err, err.stack);  
  else     console.log(data);  
});  

赤外線距離センサ使ってみた

概要

赤外線距離センサを購入したので試してみました。
物体からの距離を計測するセンサーです。

部品

距離センサー:赤外線距離センサモジュール
43円
image.png

表示機:TM1637が組み込まれた7セグLED
73円
image.png

コンピュータ:Arduino UNO互換機
699円
img.png

#配線
スクリーンショット 2020-03-26 7.52.05.png

#ソースコード

アナログ信号を受け取り、10回の平均を表示するようにしています。

  
  
#include <Arduino.h>  
#include <Wire.h>  
#include <TM1637Display.h>  
#define SERIAL_BAUD 115200  
  
#define CLK 2  
#define DIO 3  
TM1637Display display(CLK, DIO);  
#define IR_LEN 10  
int IRs[IR_LEN] = {0,0,0,0,0,0,0,0,0,0};  
int IRs_idx = 0;  
  
void setup() {  
  Serial.begin(SERIAL_BAUD);  
  while(!Serial) {}  
  
  uint8_t data[] = { 0xff, 0xff, 0xff, 0xff };  
  display.setBrightness(0x0f);  
  display.setSegments(data);  
  delay(1000);  
}  
  
void loop() {  
  int ave = 0;  
  int IR;  
  IRs_idx++;  
  if(! (IR_LEN > IRs_idx) )  
    IRs_idx = 0;  
  IRs[IRs_idx] = analogRead(A0);  
  for(int i=0 ; i<IR_LEN;i++){  
    ave+=IRs[i];  
  }  
  IR = ave/IR_LEN;  
  
  display.showNumberDec(IR, false);   
  Serial.print("IR: ");  
  Serial.print(IR);  
  delay(100);  
}  

github

少し感想

初期設定だと5cmから6cm程度の範囲で検知できます。
その範囲以外だとある100025などの最大/最小値になってしまうため、検知できません。
上部にある可変抵抗をまわすことにより調整が可能です。

動作確認

gif動画で上げても分かりにくかったので、Youtubeにて確認いただけると幸いです。
IMAGE ALT TEXT HERE

某RPGっぽいUIをCSSとHTMLだけでつくってみたよ

背景

CSSだけで色々出来ることが分かってきたので、少し作ってみたよ。
*PC版Chromeでしか確認してないよ!

名称未設定.mov.gif

実装

CheckBoxで状態変化

CheckBoxがチェックされたときだけ状態を変化させる感じ。
下記のような実装で対象となる要素の状態を変えられる

<input id="s1" type="radio" name="sel">  
<label class="sel" for="s1" id="sl1">こうげき</label>  
.nesttarget{  
/* ~~省略~~ */  
  display:none;/* 通常時は表示を消しておく */  
}  
#s1:checked ~ .nesttarget{  
  display:block;/* CheckBoxがcheckedに変化した場合に表示 */  
}  

点滅する矢印

before要素で頭に記号を付けて実装
これをアニメーションで点滅させる

/* "▶"→" "を繰り返すようなアニメーション効果 */  
@keyframes select-anime {  
    0% {content: "▶";}  
    100% {content: " ";}  
}  
#s1:checked ~ #sl1:before {  
  animation: select-anime 500ms linear infinite;  
}  

デモ

See the Pen Create a RPG-like UI with CSS and HTML only by hashito (@hashito) on CodePen.

最後に

すごく雑な記事ですが…
自分の備忘録としてのこさせてください…

DockerでMySQLなどのテスト環境を作っていたら(errno 150 Foreign key constraint is incorrectly formed)が出た話

背景

mariadbをdocker環境に移してテストしようとしたところ、30分くらい詰まってしまったのでここに供養します。

現象

外部参照用のテーブルを新規に作成しようとすると下記のエラーが出る。

ERROR 1005 (HY000): Can't create table `{dbname}`.`{tablename}` (errno: 150 "Foreign key constraint is incorrectly formed")  

原因(1)

参照しようとしている行がユニークでないためエラーになっていた。
下記のようなSQLで、重複データを削除し プレマリキーとした。

CREATE TEMPORARY TABLE {table name}_tmp AS SELECT id,MIN(uid),MIN(name) FROM tweets GROUP BY id;  
DELETE FROM {table name};  
INSERT INTO {table name} SELECT * FROM {table name}_tmp;  
DROP TABLE {table name}_tmp;  
ALTER TABLE {table name} ADD PRIMARY KEY (id);  

原因(2)

参照先と参照元の型が異なる場合に発生する。
同一の方であることを確認した。

原因(3)

テーブルのcharsetが異なる場合に発生する。
下記のコマンドで確認する。

SHOW CREATE TABLE {table name};  

とりあえず、対象テーブルを同一なcharsetに修正する。
※データが入っていると色々面倒ですが、私は何も入っていないのですんなり行きました。

ALTER TABLE {table name} CONVERT TO CHARACTER SET {char set};  

あと、外部参照がある、テーブルにも設定させる

create table{table name}(  
   {col} varchar(23) not NULL,  
    ...  
)ENGINE=InnoDB DEFAULT CHARSET={char set};  

最後に

私は1と3で発生していました。
備忘録です、忘れぬように ここに刻む

tcpdumpでping要求をみる

はじめに

tcpdumpに触る機会があったので、色々と見てみようかと思いここにまとめておきます…

環境

前の記事で作成したdocker環境を流用して、2つのPC間の通信を見てみたいと思います。

実際には片方のコンテナにアタッチして仮想ネットワーク内の通信を除く感じでやっていきます。

インストール

下記のコマンドで簡単に入ります…
MACとかは標準で入っているみたいですね。

apt install tcpdump  

コマンド

tcpdumpのコマンドは結構単純でネットワーク上のTCPプロトコルをみること、ファイルに書き込むことしか出来ない様子。

tcpdump -i eth0  

*この場合はインターフェイスをeth0に規定しています

試してみる

ping

片方のコンテナにアタッチして、中からping要求を出してみます。

ifconfig  
#eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500  
#        inet 172.19.0.2  netmask 255.255.0.0  broadcast 172.19.255.255  
#        ether 02:42:ac:13:00:02  txqueuelen 0  (Ethernet)  
#        RX packets 410  bytes 528949 (528.9 KB)  
#        RX errors 0  dropped 0  overruns 0  frame 0  
#        TX packets 241  bytes 14126 (14.1 KB)  
#        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0  
#  
#lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536  
#        inet 127.0.0.1  netmask 255.0.0.0  
#        loop  txqueuelen 1  (Local Loopback)  
#        RX packets 12  bytes 1126 (1.1 KB)  
#        RX errors 0  dropped 0  overruns 0  frame 0  
#        TX packets 12  bytes 1126 (1.1 KB)  
#        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0  
tcpdump -i eth0  
#....  
ping 172.19.0.2 -c 1  
#64 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.181 ms  
#00:59:06.976543 IP 666c78f910c9.pinet > 7bfa751bb19e: ICMP echo request, id 12, seq 1, length 64  
#00:59:06.976594 IP 7bfa751bb19e > 666c78f910c9.pinet: ICMP echo reply, id 12, seq 1, length 64  

うん…分からない…

内容を読み解く

1行目のメッセージを見てみましょう。

00:59:06.976543      # 時間  
IP                   # IP or IPv6  
666c78f910c9.pinet > # 送り元?  
7bfa751bb19e:        # 送り先?  
ICMP                 # pingはicmpってプロトコル使っていると聞いたことが…  
echo                 # ここからデータかな?  
request,             # コマンド内容?  
id 12,               # id...  
seq 1,               # シーケンス1  
length 64            # データ長?  

tcpdumpの使い方
を参考にさせていただくと、どうやらコマンドでもう少し見やすく出来るっぽい…

記事を参考に下記の2つのオプションを付与してみます。

-nn アドレスやポート番号を名前に変換しないで表示します。  
06:35:15.821137 IP 172.19.0.3 > 172.19.0.2: ICMP echo request, id 12, seq 1, length 64  
06:35:15.821207 IP 172.19.0.2 > 172.19.0.3: ICMP echo reply, id 12, seq 1, length 64  

これで、何となくですが下記のような通信が見えてきました。

  1. 172.19.0.3(コンテナB)が172.19.0.2(コンテナA)にICMPecho requestコマンドを発行
  2. 172.19.0.2(コンテナA)が172.19.0.3(コンテナB)にICMPecho replyコマンドを発行

Internet Control Message Protocol(Wikipedia)によるとICMPに規定されている通信の種類がいくつかあり、0 - Echo Reply Message8 - Echo Messageの二種類を利用して通信しているっぽい…

その他

これを試しているときに、別のコマンドが入ったので少し調べてみました。

arp

有名なARPってやつですね…

08:46:03.348573 ARP, Request who-has 172.19.0.3 tell 172.19.0.2, length 28  
08:46:03.348599 ARP, Reply 172.19.0.3 is-at 02:42:ac:13:00:03, length 28  
  1. arp172.19.0.3MAC Addres172.19.0.2が聞く
  2. arp172.19.0.3MAC Addres02:42:ac:13:00:03であることが解答される

という感じっぽいです。

Router Advertisement

こちらは、IPv6でアドレスを自動決定するときに利用するプロトコルらしいです…
IPv6ではDHCPとは違う仕組みでアドレスを決定するようですね。

08:46:35.515383 IP6 fe80::a477:c6ff:fe0c:1892 > ff02::2: ICMP6, router solicitation, length 16  

968円で作る。LEDイコライザっぽい表示機

概要

音センサを購入したので試してみました。
こちらの機器はアンプも内蔵されているため、非常に優秀とのこと…

少し感想

当初、アナログ出力をそのまま表示させていたましたが思ったような値は出ませんでした。
音声などは周波数になってしまっているため、高速フーリエ変換(fft)という計算が必要らしく。
そのモジュールを利用して出力しています。

部品

音センサー:MAX4466
133円
image.png

表示機:MAX7219ENGが組み込まれた8x8 LED
136円
image.png

コンピュータ:Arduino UNO互換機
699円
img.png

#利用モジュール

max4466
フーリエ変換のモジュールです。
下記のsiteからダウンロードして、Arduinoフォルダにコピーしてください。
http://wiki.openmusiclabs.com/

img.png img.png

MACだと下記

  
/Users/{user name}/Documents/Arduino/libraries  

max7219eng_8x8led
LEDをコントロールするモジュールです。
ArduinoのLibraryで検索し、インストールしてください
https://github.com/danidask/MatrizLed

img.png img.png

#配線
スクリーンショット 2020-03-26 7.52.05.png

#ソースコード

下記の「fft_adc」というスケッチ例をほとんど参考にしています。
http://wiki.openmusiclabs.com/

Licence:GPL licensed

/*  
fft_adc.pde  
guest openmusiclabs.com 8.18.12  
example sketch for testing the fft library.  
it takes in data on ADC0 (Analog0) and processes them  
with the fft. the data is sent out over the serial  
port at 115.2kb.  there is a pure data patch for  
visualizing the data.  
*/  
  
#define LOG_OUT 1 // use the log output function  
#define FFT_N 256 // set to 256 point fft  
  
#include <FFT.h> // include the library  
#include <MatrizLed.h>  
MatrizLed pantalla;  
  
void setup() {  
//  Serial.begin(115200); // use the serial port  
    Serial.begin(2000000); // use the serial port  
  TIMSK0 = 0; // turn off timer0 for lower jitter  
  ADCSRA = 0xe5; // set the adc to free running mode  
  ADMUX = 0x40; // use adc0  
  DIDR0 = 0x01; // turn off the digital input for adc0  
  
  pantalla.begin(12, 11, 10, 2); // dataPin, clkPin, csPin, numero de matrices de 8x8  
}  
char strbuf[64];  
void loop() {  
  while(1) { // reduces jitter  
    cli();  // UDRE interrupt slows this way down on arduino1.0  
    for (int i = 0 ; i < 512 ; i += 2) { // save 256 samples  
      while(!(ADCSRA & 0x10)); // wait for adc to be ready  
      ADCSRA = 0xf5; // restart adc  
      byte m = ADCL; // fetch adc data  
      byte j = ADCH;  
      int k = (j << 8) | m; // form into an int  
      k -= 0x0200; // form into a signed int  
      k <<= 6; // form into a 16b signed int  
      fft_input[i] = k; // put real data into even bins  
      fft_input[i+1] = 0; // set odd bins to 0  
    }  
    fft_window(); // window the data for better frequency response  
    fft_reorder(); // reorder the data before doing the fft  
    fft_run(); // process the data in the fft  
    fft_mag_log(); // take the output of the fft  
    sei();  
#if 0  
    Serial.write(255); // send a start byte  
    Serial.write(fft_log_out, 128); // send out the data  
#endif  
    int _sum = 0;  
    for(int i=0;i<128;i++){  
          _sum+=fft_log_out[i];  
    }  
    int ave = _sum/128/3;  
    int cnt=0;  
    for(int x=0;x<8;x++){  
      for(int y=0;y<8;y++){  
        if(ave > cnt){  
           pantalla.setLed(0, x, y, true);  
        }else{  
           pantalla.setLed(0, x, y, false);  
        }  
        cnt++;  
      }  
    }  
      
    memset(strbuf,0,64);  
    memset(strbuf,'|',_sum/128/3);  
    Serial.print(strbuf);  
    Serial.print("\n");  
    delayMicroseconds(1);  
  }  
}  

github

動作確認

gif動画で上げても分かりにくかったので、Youtubeにて確認いただけると幸いです。
IMAGE ALT TEXT HERE

macでheicを一括でjpgに変換するスクリプト

#はじめに
完全に個人的なメモ

こちらの記事を参考に、ループ化しただけ、忘れそうなのでここに記す。

HEICファイルをJPGファイルに変換する
https://qiita.com/1coin178/items/83098b1be474db3e8bda

#source

  
echo $1  
for f in `\find $1 -type f -name '*.heic'|sort`; do  
    echo $f  
    sips --setProperty format jpeg $f --out $f.jpg  
done  
  

こんな感じで呼び出す

./heic2jpeg.sh  {target folder}  

Riot.jsで簡単な入力値チェック

はじめに

少量のコードで入力値チェックを実装したので備忘録として…

実装

これだけです。

<test>  
 <input onInput={check_num.bind(this,"num_fx")}>  
 <input ref="num_fx" type="button" value="確定">  
 <script>  
    check_num(nm,e){  
      var f = isNaN(e.target.value);  
      self.refs[nm].disabled=f;  
      self.refs[nm].value=f?"数値を入力してください":"確定";  
    }  
 </script>  
<test>  

個人的に嫌なところ
引数に対象としたい要素名を入れなければならないのが少し嫌…
あと、f?"数値を入力してください":"確定"も固定値なのが嫌…