compression level

watch out image compression level and natural width.
should be less pixels.

Total bits = pixel x bit per pixel

    body {
      margin: 0;
    }
    img {
      float: left;
      margin-right: 10px;
      width: calc((100% - 20px)/3);
    }
img:last-of-type {
	margin-right: 0;
	}

Vector scales without quality degradation.

$0.naturalWidth
601
$0.naturalWidth
1202

Caching

db-read() -> 100ms

if request in cache,
return cache[request]

cashe is a hashtable
basic cache algorithm is below

import time

def complex_computation(a, b):
    time.sleep(.5)
    return a + b

cache = {}
def cached_computation(a, b):
    key = (a, b)
    if key in cache:
        r = cache[key]
    else:
        r = complex_computation(a, b)
        cache[key] = r
    return r

start_time = time.time()
print cached_computation(5, 3)
print "the first computation took %f second" % (time.time() - start_time)

when db query can be cashed in serverside as dictionary like below.

CACHE = {}
def top_arts();
        key = 'top'
        if key in CACHE:
            arts = CHACHE[key]
        else:
            loggin.error("DB QUERY")
            art = db.GqlQuery("SELECT * From Art "
                            "WHERE ancestor is :1"
                            "ORDER BY DESC")

        arts = list(arts)
        CACHE[key] = arts
    return arts

when posted, cache cleared.

CACHE = {}
def top_arts(update = False);
        key = 'top'
        if not update and key in CACHE:
            arts = CHACHE[key]
        else:
            loggin.error("DB QUERY")
            art = db.GqlQuery("SELECT * From Art "
                            "WHERE ancestor is :1"
                            "ORDER BY DESC")

        arts = list(arts)
        CACHE[key] = arts
    return arts

DB read should be only submission.
loadbalancer also can handle large traffic.

load balancere

n = -1
def get_server():
    global n
    n += 1
    return SERVERS[n % len(SERVERS)]

handler, url mapping DBmodel

Python Set-Cookie

Set-Cookie: name=steve; Domain=www.rddit.com; Path=/

domain is restricted wwww.

Third party set cookie such as google analytics
ad network also set cookie

Set-Cookie: user=123; Expire= Ture, 1 Jan
"session" cookie = no Expire

session cookie delete when close the browser.

def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        visits = self.request.cookies.get('visits', 0)
        if visits.isdigit();
            visits = int(visits) + 1
        else:
            visits = 0
        self.response.headers.add_header('Set-Cookie', 'visits=%s' % visits)
        if visits > 100:
            self.write("you are the best ever")
        else:
            self.write("you've been here %s times!" % visits)

write document.cookie in console.
we can rewrite cookie.

document.cookie
"wordpress_test_cookie=WP+Cookie+check; wp-settings-1=editor%3Dhtml%26libraryContent%3Dbrowse%26imgsize%3Dmedium; wp-settings-time-1=1482994300; _ga=GA1.2.511761152.1479929467"
document.cookie="wp-settings-tims-1=1482994301"
"wp-settings-tims-1=1482994301"

	

.htaccess

Order Allow,Deny
Allow from all
Deny from .abcde.com
Deny from 111.122.133.
Deny from 111.122.133.192/26

referer

SetEnvlf Referer "http://hogehoge.com" Ref1
SetEnvlf Referer "http://hogeweb.com" Ref2
Order Deny, Allow
Deny from all
Allow from env=Ref1
Allow from env=Ref2

files match

<FilesMatch "\.(gif|.jpg?g|png)$">
SetEnvlf Referer "http://hogehoge.com" Ref1
Order Deny, Allow
Deny from all
Allow from env=Ref1
</FilesMatch>
SetEnvIf REFERER "sample.com" Ref1
Order Deny,Allow
Deny from all
Allow from env=Ref1

ip

SetEnvIf REFERER "sample.com" Ref1
Order Deny,Allow
Deny from all
Allow from env=Ref1
<Files ~"\.log$">
 Deny from all
</Files>

DOSS

tmux commands

tmux is a terminal multiplexer
What is a terminal multiplexer? It lets you switch easily between several programs in one terminal, detach them (they keep running in the background) and reattach them to a different terminal. And do a lot more.

[vagrant@localhost ~]$ sudo yum -y install tmux
インストール:
  tmux.x86_64 0:1.6-3.el6
完了しました!

tmuxの起動

[vagrant@localhost ~]$ tmux new -s ProjectA

Ctrl+Bがデフォルトのコマンドプレフィックスキー

$ top
$ ctl + b + d 
->[detached]

attach

$tmux a -t ProjectA

session rename

Ctrl+b $

session list

[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]

session delete : tmux kill-serverで全て削除

[vagrant@localhost ~]$ tmux kill-session -t ProjectB
[vagrant@localhost ~]$ tmux ls
ProjectA: 1 windows (created Thu Nov 24 13:43:46 2016) [80x23]
ProjectC: 1 windows (created Thu Nov 24 13:51:07 2016) [80x23]

ctl + b + ? コマンドキー一覧表示
ctl + b + : コマンドライン表示
ctl + b + t 時計モード

ctl + b + c 新しいwindow(bash)の起動、 ctl + b + 番号、もしくは、n(next), p(previous)でwindow変更
ctl + b + . window名をつける
ctl + b + w window一覧
ctl + b + f window検索
ctl + b + & window削除

ctl + b + ” 水平分割
ctl + b + % 横分割
ctl + b + o pane移動
ctl + b + q 番号指定で移動
clt + b + {} paneの位置移動
ctl + b + x paneの解除
ctl + b + ! windowを開く

paneのサイズ変更
ctl + b : -> :resize-pane -U 5

vi ~/.tmux.conf ファイルにショートカットキーの設定、prefix keyも変更可

set -g C-t
unbind C-b
bind C-t send-prefix \; display "configuration reloaded"

bind r source-file ~/.tmux.conf 

set -g mode-keys vi

bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

session storageとlocal storage

web storageは同一オリジンでデータを保存しています。同階層、下ディレクトでも使えます。sessionStorage(タブが閉じられるまで)とloacalStorage(ブラウザ自体に保存)の二種類があります。chrome developer toolのapplicationパネルで確認できます。

%e7%84%a1%e9%a1%8c

      <script>
      (function(){
        if (typeof(Storage) === "undefined"){
          alert("web storage not supported");
        } else {
          // console.log("supported");
          // var s = sessionStorage;
          var s = localStorage;
          s.setItem('name', 'okada');
          console.log(s.getItem('name'));
        }
      })();
      </script>

setItemと削除

      <script>
      (function(){
        if (typeof(Storage) === "undefined"){
          alert("web storage not supported");
        } else {
          var ls = localStorage;
          var ss = sessionStorage;

          ls.setItem('yamada', 20);
          ls.setItem('kimura', 69);

          ss.setItem('color', 'pink');
          ss.setItem('shape', 'cube');

          // removeItem(key)
          // clear()

          ls.removeItem('yamada');
          ss.clear();
        }
      })();
      </script>

lengthとkey

      <script>
      (function(){
        if (typeof(Storage) === "undefined"){
          alert("web storage not supported");
        } else {
          var s = localStorage;

          s.setItem('okamoto', 90)
          s.setItem('murata', 60)
          s.setItem('ito', 50)

          for (var i = 0; i < s.length; i++){
            console.log(s.key(i) + ':' + s.getItem(s.key(i)));
          }


        }
      })();
      </script>

JSON(javascript object nation)

      <script>
      (function(){
        if (typeof(Storage) === "undefined"){
          alert("web storage not supported");
        } else {
          var s = localStorage;

          var user = {
            name: 'yoshida',
            score: 50
          };

          s.setItem('user', JSON.stringify(user));
          console.dir(JSON.parse(s.getItem('user')));
        }
      })();
      </script>

データの整合性

      <script>
      (function(){
        if (typeof(Storage) === "undefined"){
          alert("web storage not supported");
        } else {
          var s = localStorage;
          s.setItem('name','kurumada');

          window.addEventListener('storage', function(e){
            console.log(e.key + ':' + e.oldValue + '->' + e.newValue);
          });
        }
      })();
      </script>

Regular Expression-正規表現

      <script>
      var s = '@yamada, @sato, @ito';
      var rs = s.match(/yamada/);

      if (rs){
        console.log('マッチしました!');
      }
      </script>

キャレットを使うと、否定、下の例だと、abc以外となります。
[abc]:abc
[a-z]:a~z
[^abc]:abc以外
. :任意の一文字 /y…da/
^ :行頭 /^@yamada/
$ :行末 /@yamada$/
{} :直前の文字の繰り返し回数 0{2} ->00 0{2,}->00以上 0{2,4}->00,000,0000
[a-z]{5} ->a-zの五文字以内
[a-z]{3,6} ->a-zの3~6文字以内
a? : 0or1-> ,a
a* : 0 or more ->, a, aa, aaa
a* : 1 or more -> a, aa, aaa
() :(abc)* -> abc, abcabac
| :or ->(abc|def)
\: \n ->改行, \t ->タブ, \d ->[0-9],\w -> [a-zA-Z0-9_], \s -> スペース \メタ文字 ->メタ文字
i : 大文字小文字を区別しない -> (/yamada/i)
g : 全てのマッチした要素を配列で解す -> s.match(/a/g)
m : 複数行に対応させる -> ^$は一行のみだが、mオプションは複数行
* or + の後の?: 最小マッチ +?, *?
()RegExp s.match(/(.+?)@yamada) , RegExp.$1

<script>
      var s = '@yamada';
      var rs = s.match(/(@[A-Za-z0-9_]{1,15})/);
      console.log(RegExp.$1);
</script>
<script>
      var s = '<title>google.com</title>';
      var rs = s.match(/<title>([^<&#93;+)<\/title>/);
      console.log(RegExp.$1);
</script>

日付の取得

<script>
      var s = '2016-12-01';
      var rs = s.match(/(\d{4})[-\/](\d{2})[-\/](\d{2})/);
      console.log(RegExp.$1+'年'+RegExp.$2+'月'+RegExp.$3+'日');
</script>

sublime text3 markdown

sublime text3のコンソールに以下のコードを貼り付け、ctl + shift + pでパッケージコントロールをインストールします。

import urllib.request,os,hashlib; h = 'df21e130d211cfc94d9b0905775a7c0f' + '1e3d39e33b79698005270310898eea76'; pf = 'Package Control.sublime-package'; ipp = sublime.installed_packages_path(); urllib.request.install_opener( urllib.request.build_opener( urllib.request.ProxyHandler()) ); by = urllib.request.urlopen( 'http://packagecontrol.io/' + pf.replace(' ', '%20')).read(); dh = hashlib.sha256(by).hexdigest(); print('Error validating download (got %s instead of %s), please try manual install' % (dh, h)) if dh != h else open(os.path.join( ipp, pf), 'wb' ).write(by)
# Title 1
## Title 2
### Title 3

hr,強調、blockquote,コード、インデント

こんにちは
---
こんにちは
---
こんにちは
**strong**
> strong
'var = x'
	var = x
	var = 7

リスト、リンク、メール、画像

- item 1
- item 2
- item 3
1. item 1
2. item 2
3. item 3
<http://google.com>
<hogehoge@gmail.com>
[google][1]
[1]:http:/google.com
![book](book.jpg)

なお、マークダウン記法の中にhtmlを書くことも許されています。

github https://github.com/revolunet/sublimetext-markdown-preview

hostファイルによる192.168.33.10 のアドレス変換

hostファイル編集により、下記のように、アドレスバーのhttp://192.168.33.10:8000/を任意のパスに変更する方法です。
%e7%84%a1%e9%a1%8c

まず、Windowsキー + r のショートカットで、「drivers」のフォルダを検索します。
%e7%84%a1%e9%a1%8c

そうしたら、driversのフォルダの中からetcのフォルダを開き、その中にある、hostファイルを開きます。
%e7%84%a1%e9%a1%8c

一番下に 192.168.33.10 dev.hogehoge.com を追加して保存します。「dev.hogehoge.com」は任意のパスを設定してください。

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost

192.168.33.10 dev.hogehoge.com

すると、以降、192.168.33.10でたたいた時は、dev.hogehoge.comに変換されるようになります。