春分の日・秋分の日
春分の日・秋分の日は前年に決まる
「春分の日」及び「秋分の日」については、国立天文台が、毎年2月に翌年の「春分の日」、「秋分の日」を官報で公表しています。
春分の日・秋分の日を求める
公転時の誤差によって日にちの確定ができない春分の日ですが、何年後・何十年後の遠い将来まで予測することはできるのでしょうか。
地球の運行状態などが今のまま続くと仮定した場合、将来の春分日や秋分日も、計算で予測することが可能です。
計算
1980年を基準に1980年から2099年までの春分の日・秋分の日を計算する
#------------------------------------------------------------------ sub get_equinox_day{ #------------------------------------------------------------------ =head2 春分の日と秋分の日を求める [get_equinox_day] =over 2 指定した年の春分日・秋分日をもとめる (1980年から2099年に適用) ($vernal,$autumnal)=get_equinox_day($y); =back =cut my $s = shift; my ($yy)=@_; my ($vernal) = int(20.8431+0.242194*($yy-1980)-int(($yy-1980)/4)); my ($autumnal)=int(23.2488+0.242194*($yy-1980)-int(($yy-1980)/4)); return ($vernal,$autumnal); }
閉じれる半透明のパネル
半透明のパネルを追加
[html]
<div id="overlay" class="content"> <div class="inner"> @{[$s->panel_content()]} <div id="panel" class="panel hide"></div> </div> </div>
[css]
.content{ position:absolute; top: 375px; left:0px; width:60%; min-width:315px; display:none; z-index:100; } .inner{ padding:10px; background-color:rgba(0,0,0,0.5); }
閉じたり開いたり
<script type="text/javascript"> $(function() { $('#panel').toggle( function() { $(this).addClass('show').removeClass('hide'); $('#overlay').stop().animate( { left : - $('#overlay').width() + 20 + 'px' }, 300 ); }, function() { $(this).addClass('hide').removeClass('show'); $('#overlay').stop().animate( { left : '0px' }, 300 ); } ); $('#overlay').fadeIn(500); }); </script>
作ってみる
- 折りたためるパネルを追加(github)
- 実装してみた
- TODO
- パネルが閉じた状態から始めたい
画面
SOURCE
diff --git a/toolmmt/lib/Tool/mmt/Controller/Menu.pm b/toolmmt/lib/Tool/mmt/Controller/Menu.pm index ef1ca1f..8ed6945 100644 --- a/toolmmt/lib/Tool/mmt/Controller/Menu.pm +++ b/toolmmt/lib/Tool/mmt/Controller/Menu.pm @@ -62,4 +62,48 @@ } return $text; } + sub make_panel{ + my $s = shift; + my $text = <<END_SCRIPT; +<link rel="stylesheet" type="text/css" href="/css/demo.css" /> + +<div id="overlay" class="content"> + <div class="inner"> + @{[$s->panel_content()]} + <div id="panel" class="panel hide"></div> + </div> +</div> + +<script type="text/javascript"> + \$(function() { + \$('#panel').toggle( + function() { + \$(this).addClass('show').removeClass('hide'); + \$('#overlay').stop().animate( { left : - \$('#overlay').width() + 20 + 'px' }, 300 ); + }, + function() { + \$(this).addClass('hide').removeClass('show'); + \$('#overlay').stop().animate( { left : '0px' }, 300 ); + } + ); + \$('#overlay').fadeIn(500); + }); + window.onload = function(){ +// document.getElementById("panel").click(); + }; + +</script> + +END_SCRIPT + return $text; + } + sub panel_content{ + my $s = shift; + my $text = <<END_SCRIPT + <pre> + @{[`cal -3h`]} + @{[`date +"%a %b %d %Y"`]} + </pre> +END_SCRIPT + } 1; diff --git a/toolmmt/public/css/demo.css b/toolmmt/public/css/demo.css new file mode 100644 index 0000000..0941c15 --- /dev/null +++ b/toolmmt/public/css/demo.css @@ -0,0 +1,27 @@ +.content{ + position:absolute; + top: 375px; + left:0px; + width:60%; + min-width:315px; + display:none; + z-index:100; +} +.inner{ + padding:10px; + background:transparent url(/css/black.png) repeat top left; +} +.panel{ + position:absolute; + height:86px; + width:20px; + right:0px; + top:10px; + cursor:pointer; +} +.hide{ + background:transparent url(/css/hide.png) no-repeat center center; +} +.show{ + background:transparent url(/css/show.png) no-repeat center center; +} diff --git a/toolmmt/templates/menu/menu.html.ep b/toolmmt/templates/menu/menu.html.ep index ec27318..48724f8 100644 --- a/toolmmt/templates/menu/menu.html.ep +++ b/toolmmt/templates/menu/menu.html.ep @@ -1,5 +1,6 @@ % layout 'default'; % title 'menu' ; +%== $self->make_panel(); <table width=98%><tr><td style="vertical-align: top;"> % for my $r (@$_data){ % if ($r->{menukbn} =~ /^(H\d)/i){
パスフレーズの入力内容を確認出来る様にする
パスワードからパスフレーズへ
あのパスワード規則、実は失敗作だった数字・記号・大文字の組み合わせ、2003年に考案した人物が後悔しているらしい。
- パスワードのルールは間違いだった
- 「NISTスペシャルパブリケーション800-63」は今年2017年6月に全面改定
- 「パスワード」ではなく、スペースも入れられる最低64文字の「英単語の組み合わせによるパスフレーズ」の使用を推奨
- ユーザーがパスワードを変更すべきなのは、盗まれた兆候があった時だけ
ログイン画面
なが~いパスフレーズ(漢字を含む)を入力できる様にすると入力内容を確認したくなるのでパスフレーズを確認出来る様にした。
チェックボックスのクリックでパスワードの表示を切り替えるサンプル画面
Index: templates/auth/login.html.ep =================================================================== --- templates/auth/login.html.ep (revision 145) +++ templates/auth/login.html.ep (working copy) @@ -6,8 +6,21 @@ <br>Name: %= text_field 'user',size => 60 <br>password: - %= text_field 'passwd',size => 60 + %= text_field 'passwd',size => 60,id=>"passwd" <br> + <input type="checkbox" id="password-check" checked="checked">パスワードを表示する + <br> %= submit_button 'Login' %= hidden_field url => $url % end +<script> + const pwd = document.getElementById('password'); + const pwdCheck = document.getElementById('password-check'); + pwdCheck.addEventListener('change', function() { + if(pwdCheck.checked) { + passwd.setAttribute('type', 'text'); + } else { + passwd.setAttribute('type', 'password'); + } + }, false); +</script>
- アンドロイドではpassword fieldでは日本語がいれられないのね、どうしよう・・・
セッションとユーザー紐づけ
mojoliciusでセッションとユーザーを紐づけしてみた
LOGIN画面で認証したユーザーをセッションと紐づけてDBに登録しクッキーに保存したセッションにて以降の画面でユーザーを認識する。
- セッションが有効で無い時は認証画面を表示する。
- 認証画面での入力したユーザーとパスワードにてDBに登録したパスワードのハッシュ値と照合しパスワードの有効性を確認する。
- 入力値が有効の場合にセッションとユーザーを紐づけでDBに登録する。
- 元画面に戻る。
中置記法から抽象構文木(AST)変換し後置記法(逆ポーランド記法)の計算
吉祥寺.pm #20 へ行ってきた
東京に出張に来ていたので2019/11/22吉祥寺.pm #20へ行ってきた。色々と刺激を受けた。発表のなかで、めもりー(@m3m0r7)さんの『PHP で AST 解析して Java の中間コードを生成する』に刺激を受けて、中置記法から抽象構文木(AST)変換し後置記法(逆ポーランド記法)の計算を作ってみた。以前に中置記法から後置記法(逆ポーランド記法)への変換と計算でスタックを使った逆ポーランド記法のプログラムを作ったが、今回はASTで計算してみた。(当然paerlで)
https://kabukawa.hatenablog.jp/entry/2019/11/25/012334 <-良くまとっ待っている
Source
実行
$ perl ast.pl 10+1 10 + 1 11 $
mojoliciousで動くように修正した。
ast.pl
use lib 'lib'; use Ast; use Data::Dumper; my $c = Ast->new; #my $t = $c->adjust('(100+2**3-((1+2)/(4+-2))*(-10))'); my $t = $c->adjust(join '',@ARGV); $c->item_split($t); my $root = $c->makeTree(@{$c->{item}}); print "$t\n"; print $c->readTree($root),"\n";;
Ast.pm
package Ast; use strict; use warnings; use Data::Dumper; my $op = +{ '-' => [sub {$_[0] - $_[1]},1], # オペレータ定義 '+' => [sub {$_[0] + $_[1]},1], '*' => [sub {$_[0] * $_[1]},2], '/' => [sub {$_[0] / $_[1]},2], '%' => [sub {$_[0] % $_[1]},2], '**' => [sub {$_[0] ** $_[1]},3], #'x' => [sub {$_[0] * $_[1]},8], # 多項式対応? '(' => [sub { },9], ')' => [sub { },10], }; sub ast{ Ast->new('formula'=>shift())->{anser}; } sub _ast{ my $s = shift; $s->{anser} = $s->readTree($s->makeTree(@{$s->item_split($s->adjust(shift))->{item}})); } sub new { # コンストラクター my $class = shift; my $self = {@_}; bless $self,$class; $self->setReOps(); $self->_ast($self->{formula}) if (exists $self->{formula}); return $self; } sub setReOps{ # 演算子の正規表現作成 my $s = shift; $s->{ops} = join ('|',map {s/(.)/\\$1/g;$_;} sort {length $b <=> length $a} keys %$op); $s->{ops} = "(".$s->{ops}.")"; return $s; } sub newNode{ my $s = shift; return {data => shift(),left =>shift(),right=>shift()}; } sub readTree{ # AST計算 my ($s,$node) = @_; do{$node->{$_} = $s->readTree($node->{$_}) if(ref($node->{$_}) eq "HASH")} for ('left','right'); exists $op->{$node->{data}} ? $op->{$node->{data}}->[0]($node->{left},$node->{right}) : $node->{data}; } sub makeTree{ # ATS組み立て my $s = shift; while($_[0] eq '(' and $_[-1] eq ')'){ my ($r,$sw) = (0,0); for(@_){ # '('の深さを計算 $r++ if($_ eq '('); $r-- if($_ eq ')'); $sw++ if($r == 1 and $_ eq '('); } if($sw == 1){ # 一番外側の括弧を外す shift; pop; }else{ last; } } return shift() if(@_ <= 1); # 要素が一つの時は要素を返す my ($prio,$i,$m,$r) = (99,-1,0,0); for(@_){ # 一番右側の一番プライオリティの低いオペレータを検索 $i++; if(/^$s->{ops}$/){ $r++ if($_ eq '('); $r-- if($_ eq ')'); next if($r or $_ eq ')'); # 括弧の間は読み飛ばす if($op->{$_}->[1]+$r <= $prio){ $prio = $op->{$_}->[1]; $m = $i; } } } return $s->newNode($_[$m], # オペレータとオペランド(右と左)を返す $s->makeTree(@_[0 .. $m-1]), $s->makeTree(@_[$m+1 .. $#_]) ); } sub item_split{ # 計算式を要素に分解 my $s = shift; my $text = shift || $s->{_text}; $s->{item} = [split ' ',$text]; return $s; } sub adjust{ # 計算式の要素をスペースで分割 my ($s,$text) = @_; $text =~ s/$s->{ops}/ $1 /g; $text =~ s{([\d\)])\s*\(}{$1 \* \(}g; # 開き括弧の前が演算子じゃない時に*を補完 ex). (1+2)(2-1) -> (1+2)*(2-1) $s->{_text} = $text =~ s/($s->{ops}\s*-)\s*/$1/g; return $text; } 1;
--
mojoliciousでユーザー認証
LOGIN画面を追加
mmt.pm
Router認証処理を追加する。underで各処理の前に認証済みの確認処理を追加。認証を必要としない処理は元々のRouterを使う。
--- a/toolmmt/lib/Tool/mmt.pm +++ b/toolmmt/lib/Tool/mmt.pm @@ -16,15 +16,20 @@ sub startup { # Router my $r = $self->routes; $r->namespaces(['Tool::mmt::Controller']); + # ユーザー認証 + my $sr = $r->under->to('auth#check'); # Normal route to controller $r->get('/')->to('example#welcome'); - $r->get('/mmt/:_table/desc')->to('mmt#desc'); - $r->get('/mmt/:_table')->to(controller => $self->controller,action =>'mainform'); - $r->post('/mmt/:_table')->to(controller => $self->controller,action => 'registry'); - $r->get('/mmtx/:controller')->to(controller => $self->controller,action =>'mainform'); - $r->post('/mmtx/:controller')->to(controller => $self->controller,action => 'registry'); - $r->any('/mmtx/:controller')->to(controller => $self->controller,action => 'mainform'); - $r->any('/rwt/:controller')->to(controller => $self->controller,action => 'print_main'); + $sr->get('/logout')->to('auth#logout'); + $sr->any('/login')->to('auth#login'); + $sr->any('/mmt/login')->to('auth#login'); + $sr->get('/mmt/:_table/desc')->to('mmt#desc'); + $sr->get('/mmt/:_table')->to(controller => $self->controller,action =>'mainform'); + $sr->post('/mmt/:_table')->to(controller => $self->controller,action => 'registry'); + $sr->get('/mmtx/:controller')->to(controller => $self->controller,action =>'mainform'); + $sr->post('/mmtx/:controller')->to(controller => $self->controller,action => 'registry'); + $sr->any('/mmtx/:controller')->to(controller => $self->controller,action => 'mainform'); + $sr->any('/rwt/:controller')->to(controller => $self->controller,action => 'print_main'); $r->any('/api/:controller/:action')->to('example#welcom'); }
Auth.pm
認証処理は全てAuth.pmに押し込む。Routerのunderにて全ての処理の前にcheckを実行しsessionが確立していればreturn 1にて終了し、確立していない時はユーザー認証画面に繊維する。(ユーザー認証(userAuth)処理は未だ無い)
--- /dev/null +++ b/toolmmt/lib/Tool/mmt/Controller/Auth.pm @@ -0,0 +1,54 @@ +package Tool::mmt::Controller::Auth; +use Mojo::Base 'Tool::mmt::Controller::Mmt'; + +sub login { + my $s = shift; + $s->redirect_to($s->param('url')) if $s->param('url'); + $s->render( template => 'mmt/index'); +} +sub check { + my $s = shift; + # セッション確定済なら認証通貨 + if($s->session('session')){ + return 1; + } + #パスワードチェック + if($s->userAuth()){ + return 1; + } + $s->stash( 'url' => $s->req->url->to_abs ); + $s->render( template => 'auth/login'); + return undef; +} +sub userAuth{ + my $s = shift; + my $user = $s->param('user')||''; + my $pass = $s->param('passwd')||''; + if ($user eq '' or $pass eq '' or $user =~ /(admin|root)/i){ + $s->param('user','guest'); + $s->param('passwd','guest01'); + return undef; + } + my $sessionId = $s->randomStr(); + $s->session('session' => $sessionId); + return 1; +} +sub logout{ + my $s = shift; + # セッション削除 + $s->session(expires => 1); + $s->stash( 'url' => 'login' ); + $s->render( template => 'auth/login'); +} +sub randomStr{ + my $s = shift; + my %arg = (-length =>16, + -str => (join '',('A'..'Z','a'..'z','0'..'9')), + @_); + my @str = split //,$arg{'-str'}; + my $str = ""; + for(1 .. $arg{'-length'}){$str .= $str[int rand($#str+1)];} + return $str; +} + +1;
auth/login.html.ep
ログイン画面
--- /dev/null +++ b/toolmmt/templates/auth/login.html.ep @@ -0,0 +1,13 @@ +% layout 'defrwt'; +% title 'login' ; +<h2>Login</h2> + +%= form_for login => (method => 'post') => begin + <br>Name: + %= text_field 'user' + <br>password: + %= text_field 'passwd' + <br> + %= submit_button 'Login' + %= hidden_field url => $url +% end
default.html.ep
デフォルト画面にlogoutのリンクを追加
--- a/toolmmt/templates/layouts/default.html.ep +++ b/toolmmt/templates/layouts/default.html.ep @@ -50,6 +50,7 @@ <body> <input type=hidden name=_focus id=_focus value=<%= param('_focus') %>> <div class="main"> + <a href=/logout>logout</a> <%= content %> </div> <div class="sidebar">
mmt/index.html.ep
ログイン後のスタートページ
--- /dev/null +++ b/toolmmt/templates/mmt/index.html.ep @@ -0,0 +1,3 @@ +% layout 'default'; +% title "mmt - index " ; +<h1>INDEX</h1>