14. 雑多な話題
本日の話題
新版EpisoPass
情報処理との闘い
ローカルファイルを撤廃
登録インタフェース
P5.jsの楽しみ
情報共有により広がる世界
インターネットの三大発明
https://gyazo.com/64bf54e9388c0c4e737d7bef443e4860
EpisoPass
https://gyazo.com/52ff5f7d532bfe2f637d37b958734fe8 http://www.pitecan.com/p/Amazon_masui@pitecan.com.html
増井のパスワード多数
「増井のパスワード」でググっても出る
EpisoQ
EpisoPass問題を簡単に作るコマンド
% npm install -g episoq
% episoq
「情報処理との闘い」
「情報処理」とは
コンピュータによる計算のこと?
情報処理との闘いは解決するか?
upload, goquick, episopass, ...
ローカルファイルの撤廃
重要データはすべてWebにある
Amazon S3, Dropbox, Google Drive, Box, ...
ローカルファイルは微妙なものばかり
どこかのパソコンにだけ入ってるデータはあるか?
ローカルファイルの例
貰い物のPDF
スキャンデータ
写真、ビデオ
ローカルファイルの問題
別のパソコンで見られない
分類が難しい
カテゴリ? 時期? 名前?
置き場所が確定していない
いろんなところに領収書があったりする
解決方法
微妙なファイルは全部アップロード
Scrapboxで管理
利点
ローカル管理のファイルがゼロになる
階層に悩む必要がない
これから実験する予定
写真管理
便利かつ面白い
デジカメ以前は不可能だった
登録インタフェース
重要情報はすべてネット上
個人情報
共有情報
ネット上のデータ登録方法が重要
ネット上の個人情報
メール (IMAP)
ファイル (Evernote, Dropbox, etc.)
メモ (Wiki)
予定表 (Wiki)
ブックマーク
ネット上の共有情報
ファイル (GitHub, GoogleDocs, etc.)
メモ (Wiki)
ブックマーク (はてブ)
変換辞書もこれからはWeb上
ATOK
Wiki上の変換辞書
https://gyazo.com/e4a1e9ad62df6c8b07ddd5b42fc0e08d http://Scrapbox.io/Gictionary/%E9%AB%98%E9%80%9F%E9%81%93%E8%B7%AF
デモ: Chaim
Chrome拡張機能で動作
辞書もプログラムもWebにあるようなもの
登録の敷居
検索は普及してきた
誰もがいつでもどこでもググっている
登録は敷居が高い
登録を簡単にする方法、登録情報を活用する方法が今後の課題
検索の普及
現在は誰でもどこでも検索している
ググる
ページ内検索
書店、図書館
これは最近の現象
ひと昔前は誰も検索してなかった
検索システムのある場所にでかけていた
登録も状況は変わるかも?
検索/入力/登録
実は似たようなもののはず
別物と思われている
登録を普及させる方法
登録の敷居を低くする
自動登録 / 自動セーブ
検索と登録の統合
登録専用アプリケーション
登録の順序を変える
登録すると楽しいシステム
簡単登録
登録ブックマークレット
3memo / GoQuick
Gyazo
ブックマークレット
JavaScriptプログラムをブックマークとしてメニューに登録
メニューからブックマークを選ぶとJavaScriptプログラムが動く
登録ブックマークレット
はてな
本棚
3memo
ネット上のブックマーク
URLや文字列に短いURLを割り当て
c.f. TinyURL
ショートカット的に利用
GoQuick: パーソナルな3memo
情報が他人に見えない
https://gyazo.com/a7cad24bdebab4107bd84368425547dc
Web上で書籍情報共有
http://gyazo.com/4401b49e940bb988040ec683a225ef3e.png
本棚.orgの登録ブックマークレット
code:hondana.js
javascript:var src=document.location.href+
document.body.innerHTML;
re=new RegExp('(product|ASIN)/(0-9{9}0-9X)'); if(src.match(re)){void(window.open(
デモ: 本棚.orgへの登録
画像を楽々アップロード
自動登録機能追加 (2015/6)
http://gyazo.com/ http://gyazo.com/23cc49972359958068281742189be6de.png
Gyazoの自動登録機能
画面クリップ時にメタデータを登録
時刻
アプリ名
URL
ページタイトル
連想検索で利用
IvySearch
http://gyazo.com/997642f12b6649a8b4586d68ecb4f5cb.png
Gyazoの「芋蔓検索」
「神戸」
「記事」
「請求書」
Gyazoのコメント登録
面倒だと思われることが多い
ファイル名を考える方が面倒なのに?
自動登録 / 自動セーブ
大抵のアプリケーションやサービスでは自動セーブを行なわない
明示的にセーブ操作が必要
これは昔の名残
なんでも自動セーブ / 自動的登録すると便利
エディタの自動セーブ
Emacsのauto-save-buffers
デモ: Emacsの自動セーブ
Wikiの自動セーブ
編集結果を自動セーブすると楽
Scrapboxはすべて自動セーブ
URLの自動セーブ
閲覧したページを全部記録
Webページ閲覧の統計
何パーセントぐらいのページを再訪しているか?
Webページ閲覧の統計
何パーセントぐらいのページを再訪しているか?
アクセスの<strong>2/3</strong>は以前見たページの再訪
増井の場合
1日平均約600ページ
2/3は以前に見たページ
SNSなど以外は100ページ程度
本当に新しいページを見るのは30ページ程度
全部自動記録してもたかがしれている
貧乏根性のせい
一生休まず文字入力しても10GBぐらい
なんでも全部セーブしても全然問題ない
検索と登録
3memo, GoQuickの場合
XYZ! で登録モード
XYZ で呼び出し
登録されていない場合はGoogle検索
検索と登録の融合
入力/検索/登録は普通は別システム
e.g. 単語の入力/検索/登録
検索操作と登録操作をシームレスにしたい
Gyaimの単語登録手順(1)
登録したい単語をコピー
単語の読みを入力
登録したい単語が候補に出る
候補を選択すると登録完了
Gyaimの単語登録手順(2)
単語の読みを入力
ググった結果が候補に出る
候補を選択すると登録完了
デモ: Gyaimの単語登録
Gyaimの単語登録
検索結果を例示
一種の例示インタフェース
検索結果にエントリを加える = 登録
様々な検索システムに登録機能を融合可能
e.g. 画像検索結果に新たな画像を加える
P5.jsの楽しみ
https://p5js.org/ https://gyazo.com/42aa53c84d93659034f52370ca11e427
ProcessingのJavaScript版
四文字熟語クイズ
https://runp5.com/?code=https://scrapbox.io/api/code/masui/四文字熟語データ/fourdata.js,https://scrapbox.io/api/code/masui/四文字熟語クイズ/four.js&css=https://fonts.googleapis.com/css?family%3dKosugi%20Maru https://gyazo.com/a1c05a95c84a8a33d3934be7928ae6df
P5.jsを動かす
(将来なくなる可能性あり)
ブラウザで動かすことが推奨
ドキュメントとサンプル
https://gyazo.com/c096a74372317bcfef987fb1a95e92a5
チュートリアル
P5.jsの書籍
https://images-fe.ssl-images-amazon.com/images/I/51DCOj5HYVL._AC_US320_FMwebp_QL65_.jpg
https://images-na.ssl-images-amazon.com/images/I/61wLQ8X0G-L._SX379_BO1,204,203,200_.jpg
P5をScrapboxで動かす
コード記法でプログラムを記述
code:test.js
alert('abc');
Create a link for running it
FireBase利用
「文芸的プログラミング」スタイル
例: 正規分布の生成
https://gyazo.com/edbeca3c66ed7606e6fcc27dbf9b5bc8
code:normal.js
// Adding 10 random numbers and show the distribution
function setup(){
createCanvas(400,400)
histogram = []
for(i=0;i<100;i++) histogrami = 0 strokeWeight(0)
}
function draw(){
val = 0
for(i=0;i<10;i++) val += random(1/10)
fill('#ff0')
rect(0,0,400,400)
fill('blue')
for(i=0;i<100;i++)
rect(i*4,400-histogrami,4,histogrami) }
例: 結城氏のプログラム
https://gyazo.com/86adfa800b4f9976fdfe65613c54593c
code:yuki.js
T=0
function setup(){
createCanvas(600,600)
noStroke()
}
function draw() {
fill('#000')
rect(0,0,600,600);
N=100
S=300
for (n=1; n<N; n++) {
r=n*2
fill('#fff')
R=(N-n)/10
t=T*n
ellipse(S+r*cos(t),S-r*sin(t),R,R)
T+=0.00001
console.log(T)
}
}
例: 山辺氏のプログラム
https://gyazo.com/0f86aad2c6be7650ad8a4ceea95b5d7f
code:rz.js
function setup(){
createCanvas(600,600);
background(128);
}
function draw(){
x = random(0,width);
y = random(0,height);
w = random(2,20);
noStroke();
if(x % 60 < 35)//xを60で割った余りが35未満だったら
fill(0,0,0);
else
fill(255,255,255);
ellipse(x, y, w, w);
}
Hello World
code:hello.js
alert('Hello, world!');
https://runp5.com/sfc-web2019/14._雑多な話題/hello.js
数値計算
$ \sqrt{2}
code:sqrt.js
value = 100
for(;;){
alert(value)
value = (value + 2/value) / 2
}
特殊関数
setup()
初期化
draw()
フレームごとに呼ばれる
線の描画
code:line.js
function setup(){
line(0,0,100,100);
}
矩形描画
code:rect.js
function setup(){
rect(10,10,80,80);
}
矩形描画
code:boldrect.js
function setup(){
stroke(255, 255, 0); // yellow
strokeWeight(10);
rect(10,10,80,80);
}
矩形描画
code:fillrect.js
function setup(){
fill('#00f'); // blue
rect(10,10,80,80);
}
円描画
code:circle.js
function setup(){
ellipse(50,50,30,30);
}
Using draw()
code:randrect.js
function setup(){
createCanvas(400, 400)
strokeWeight(0)
}
function draw(){ // called 30? times in a second
fill('blue')
posx = random(0,400)
posy = random(0,400)
rect(posx,posy,10,10)
}
Using draw()
code:randrect2.js
function setup(){
createCanvas(400, 400)
strokeWeight(0)
}
function draw(){
clear()
fill('blue')
posx = random(0,400)
posy = random(0,400)
rect(posx,posy,10,10)
}
Using mouse position
code:mouse.js
function setup(){
createCanvas(600, 600)
}
function draw(){
clear()
stroke('blue')
line(0,0,mouseX,mouseY) // predefined mouse coordinates
}
Getting mouse event
code:mouseevent.js
var value = 0;
function draw() {
fill(value);
rect(25, 25, 50, 50);
}
function mousePressed() {
if (value == 0) {
value = 255;
} else {
value = 0;
}
}
Drawing circles
https://gyazo.com/0ec9a6ad4dc1f39c260d34439bf827a8
code:drag.js
function setup() {
createCanvas(400,400);
fill(0);
}
function mouseDragged(){
ellipse(mouseX, mouseY, 20, 20);
}
Mouse move event
code:follow.js
function setup(){
createCanvas(400,400);
}
function draw(){
clear();
fill(0,0,255);
rect(mouseX,mouseY,40,40);
}
Drawing a fractal tree
code:tree.js
// The Nature of Code
// Daniel Shiffman
// Recursive Tree
// Renders a simple tree-like structure via recursion
// Branching angle calculated as a function of horizontal mouse position
var theta;
function setup() {
createCanvas(640, 360);
}
function draw() {
background(51);
// Let's pick an angle 0 to 90 degrees based on the mouse position
theta = map(mouseX,0,width,0,PI/2);
// Start the tree from the bottom of the screen
translate(width/2, height);
stroke(255);
//branch(120);
branch(mouseY); // Y座標で深さを変えるようにしてみた
}
function branch(len) {
// Each branch will be 2/3rds the size of the previous one
var sw = map(len,2,120,1,10);
strokeWeight(sw);
//strokeWeight(2);
line(0, 0, 0, -len);
// Move to the end of that line
translate(0, -len);
len *= 0.66;
// All recursive functions must have an exit condition!!!!
// Here, ours is when the length of the branch is 2 pixels or less
if (len > 2) {
push(); // Save the current state of transformation (i.e. where are we now)
rotate(theta); // Rotate by theta
branch(len); // Ok, now call myself to draw two new branches!!
pop(); // Whenever we get back here, we "pop" in order to restore the previous matrix state
// Repeat the same thing, only branch off to the "left" this time!
push();
rotate(-theta);
branch(len);
pop();
}
}
エスカレータのシミュレーション
code:escalator.js
STRATEGY1 = 0; // left
STRATEGY2 = 1; // right
lspeedfactor = 1.0;
lgapfactor = 1.0;
rspeedfactor = 2.0;
rgapfactor = 3.0;
strategy = STRATEGY2;
var pair = location.search.substring(1).split('&');
for(var i=0; pairi; i++){ var kv = pairi.split('='); if(kv0 == 'ls') lspeedfactor = kv1; if(kv0 == 'lg') lgapfactor = kv1; if(kv0 == 'rs') rspeedfactor = kv1; if(kv0 == 'rg') rgapfactor = kv1; }
MOVING_LOWER = 0;
WAITING_LOWER = 1;
ASCENDING = 2;
UPPER = 3;
LEFT = 0;
RIGHT = 1;
llane = 220.0;
rlane = 250.0;
escheight = 460.0;
WINWIDTH = 500;
WINHEIGHT = 500;
NPERSONS = 50;
NSTAIRS = 15;
STAIRHEIGHT = 60;
STEPUNIT = 1;
steppos = 0;
waiting_l = 0;
waiting_r = 0;
done = false;
xspeed = 1.0;
persons = [];;
loops = 0;
var Person = function(){
this.x = 0.0;
this.y = 0.0;
this.status = MOVING_LOWER;
this.lr = LEFT;
};
function setup(){
createCanvas(WINWIDTH,WINHEIGHT);
frameRate(60);
for(var i=0;i<NPERSONS;i++){
}
}
function can_ascend_l(n){
var result = true;
for(var i=0;i<n;i++){
if(personsi.status == ASCENDING && personsi.y - personsn.y < STAIRHEIGHT * lgapfactor){ return false;
}
}
return true;
}
function can_ascend_r(n){
for(var i=0;i<n;i++){
if(personsi.status == ASCENDING && personsi.y - personsn.y < STAIRHEIGHT * rgapfactor){ return false;
}
}
return true;
}
function can_forward_lower(n){
for(var i=0;i<n;i++){
if(personsi.status == MOVING_LOWER && personsi.x - personsn.y < 30.0){ return false;
}
}
return true;
}
function can_forward_upper(n){
for(var i=0;i<NPERSONS;i++){
if(personsi.status == UPPER && personsi.x - personsn.x > 0.0 && personsi.x - personsn.x < 30.0){ return false;
}
}
return true;
}
function all_upper(){
for(var i=0;i<NPERSONS;i++){
if(personsi.status != UPPER) return false; }
return true;
}
function draw(){
if(done) return;
background(213,200,255);
for(var i=0;i<NSTAIRS;i++){
y = i * STAIRHEIGHT + steppos;
//line(llane-10+10,WINHEIGHT-y,rlane+10+20+10,WINHEIGHT-y);
fill(200,200,200);
strokeWeight(0);
rect(llane-10+10,WINHEIGHT-y,rlane-llane+40,STAIRHEIGHT/2);
}
steppos += STEPUNIT;
if(steppos >= STAIRHEIGHT){
steppos = 0;
}
for(var i=0;i<NPERSONS;i++){ // 駒をひとつずつ進める。
case MOVING_LOWER: // 下で移動中
if(personsi.x >= llane && // 左レーンまでたどりついたとき if(strategy == STRATEGY1){
if(waiting_l == 0 || waiting_l < waiting_r){
personsi.status = WAITING_LOWER; waiting_l++;
}
else {
personsi.lr = RIGHT; // 右で待つことにする }
}
else if(strategy == STRATEGY2){
if(waiting_l < waiting_r){
personsi.status = WAITING_LOWER; waiting_l++;
}
else {
personsi.lr = RIGHT; // 右で待つことにする }
}
}
else if(personsi.x >= rlane && // 右レーンまでたどりついたとき personsi.status = WAITING_LOWER; waiting_r++;
}
if(can_forward_lower(i)){ // 前に進める場合は一歩前に移動する
}
break;
case UPPER: // エスカレータからおりていて
if(can_forward_upper(i)){ // 前に進める場合は一歩前に移動する
}
break;
case WAITING_LOWER: // エスカレータ待ち状態で、
if(personsi.lr == LEFT && // 左で待っていて can_ascend_l(i) // 上に余地がある
){
personsi.status = ASCENDING; waiting_l--;
}
else if(personsi.lr == RIGHT && // 右で待っていて can_ascend_r(i) // 上に余地がある
){
personsi.status = ASCENDING; waiting_r--;
}
break;
case ASCENDING: //エスカレータに乗っていたら
if(personsi.y >= escheight){ // エスカレータで上まで到達していればおりる }
else {
personsi.y += STEPUNIT * lspeedfactor; // 1段上に移動する }
else {
personsi.y += STEPUNIT * rspeedfactor; // 1段上に移動する }
}
break;
}
}
strokeWeight(1);
for(var i=NPERSONS-1;i>=0;i--){
fill(255,255,0);
rect(personsi.x+10,WINHEIGHT-30-personsi.y,20,20); fill(0,0,0);
text(i+1,personsi.x+10+3,WINHEIGHT-30-personsi.y+14); }
if(! all_upper()){
loops++;
}
else {
done = true;
}
fill(0,0,0);
// text(millis(),20,20);
text(loops,20,20);
}
音を出す
code:sin.js
// canvas is not created if setup() is not defined
freq = $('<div>').text('440').appendTo($('body')) // div for freq
freqval = 440;
osc = new p5.TriOsc(); // set frequency and type
osc.amp(0.5);
osc.start();
$('<div>').appendTo($('body')).slider({ // jQuery UI slider
min: 50,
max: 1200,
value: 440,
slide: (event, ui) => {
freqval = ui.value
osc.freq(freqval)
freq.text(freqval)
osc.start()
}
});
情報共有により広がる世界
重要情報をみつける方法
認証局を使わずに情報の存在を証明
重要なファイルとは?
× 動画ファイル
× システムファイル
× MP3
○ 自分が撮った写真
○ アイデアメモ
サイズやファイル属性から判定できない
重要なファイルの特徴
自分だけが持っているファイルは重要
○ 自分が撮った写真
○ アイデアメモ
重要度の判定
ファイルのハッシュ値を登録サイトに登録
自分以外に誰も登録していないものは重要
他人とのファイル共有の視覚化
http://gyazo.com/5124de74689ff55d53ffb3da92c1c636.png
自分のディスク内の重複ファイル
http://gyazo.com/4418725289623822fa490081d48ec670.png
HashInfo.com
手持ちのファイルのハッシュと属性を登録
ユーザが増えると重要度を判定できるようになる
情報の存在証明
公証役場を利用
認証局を利用
手間と金がかかる
登録による存在証明
証明したいファイルのハッシュを計算
e.g. 0a1b2c3d
それを含むURLを生成
e.g. http://example.com/0a1b2c3d
ソーシャルブックマークに登録
はてなブックマーク
del.ico.us
ソーシャル存在証明
F = 存在を証明したいファイル
ある時点において F が存在したことを証明したい
authコマンド
F: 存在を証明したいファイル
H ← F のハッシュ (e.g. 0a1b2c3d)
U ← H含むURL (e.g. http://3memo.com/masui/0a1b2c3d)
S ← 保護されたURL (e.g. http://pitecan.com/secret)
F を S にコピー
S を U に登録
U を各種SBMに登録
存在証明
U はあちこちに登録されている
タイムスタンプも登録されている
Uの偽造は不可能
F が存在しない時点で U を登録することは不可能
⇒ U が登録されている時点で F が存在したことがわかる
ソーシャル存在証明
アイデア段階
裁判などで勝てるかどうかは不明
共有しつつ情報を保持する方法
ステガノグラフィー
大事なものを共有するときはステガノグラフィーが有用なことも?
秘密データを普通のデータ中に埋め込む
暗号化したことが一見わからないようにする
ステガノグラフィー例
オリジナル画像
http://masui.org.s3.amazonaws.com/2/2/225079322c2281a0d9c2698e34b07d7c.jpg
ステガノグラフィー例
40バイトのデータを埋め込んだもの
http://masui.org.s3.amazonaws.com/0/0/00a809645da912a650563f5de08a761e.jpg
ステガノグラフィー例
200バイトのデータを埋め込んだもの
http://masui.org.s3.amazonaws.com/3/2/32238e884aad99a08526690fe428a809.jpg
漫画への情報埋め込み
http://gyazo.com/e09556d75f21d725b6751683ae015e99.png
漫画への情報埋め込み
集中線などにデータを埋め込めば良い?
http://gyazo.com/a6027ae7fa53f4c4cab05cfaf36abf95.png
まとめ