<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel rdf:about="https://let.hatelabo.jp/moriyoshi/rss">
    <link>https://let.hatelabo.jp/moriyoshi/rss</link>
    <description></description>
    <title>Bookmarklets from moriyoshi</title>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="https://let.hatelabo.jp/moriyoshi/let/gYC-xpqP_umEVw"/>
        <rdf:li rdf:resource="https://let.hatelabo.jp/moriyoshi/let/gYC-xqCk9YbnUg"/>
        <rdf:li rdf:resource="https://let.hatelabo.jp/moriyoshi/let/gYC-xpWhwP_eQg"/>
      </rdf:Seq>
    </items>
  </channel>
  <item rdf:about="https://let.hatelabo.jp/moriyoshi/let/gYC-xpqP_umEVw">
    <link>https://let.hatelabo.jp/moriyoshi/let/gYC-xpqP_umEVw</link>
    <dc:date>2010-07-01T02:07:59Z</dc:date>
    <description>顔画像に遮眼帯をつけます。</description>
    <dc:creator>moriyoshi</dc:creator>
    <title>[Let] 遮眼帯ブックマークレット</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2Fmoriyoshi%2Flet%2FgYC-xpqP_umEVw.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;遮眼帯ブックマークレット&lt;/a&gt;&lt;pre&gt;/*
 * @title 遮眼帯ブックマークレット
 * @description 顔画像に遮眼帯をつけます。
 * @include http://*
 * @license MIT License
 * @require jQuery
 */
(function() {
var proxiedAjax = function(options) {
    var merged_options = {};
    var url = options[&amp;quot;url&amp;quot;];
    if (typeof options.data != &amp;quot;undefined&amp;quot;) {
        url = url.replace(/\?|$/, function(g) {
            return &amp;quot;?&amp;quot; + $.param(options.data);
        });
    }
    $.extend(merged_options,
        options,
        {
            url: &amp;quot;http://query.yahooapis.com/v1/public/yql&amp;quot;,
            data: {
                format: &amp;quot;json&amp;quot;,
                q: &amp;quot;select * from xml where url='&amp;quot;
                   + url.replace(/'/g, &amp;quot;''&amp;quot;) + &amp;quot;'&amp;quot;
            },
            dataType: &amp;quot;jsonp&amp;quot;,
            success: function(data) {
                options[&amp;quot;success&amp;quot;](data.query.results);
            }
        }
    );
    return $.ajax(merged_options);
};

var makeInt = function(x) {
    retval = {}
    for (var i in x) {
        if (x.hasOwnProperty(i)) {
            var v = x[i];
            if (typeof v == &amp;quot;string&amp;quot; || v instanceof String)
                v = parseInt(v);
            else
                v = makeInt(v);
            retval[i] = v;
        }
    }
    return retval;
};

var main = function() {
    $(&amp;quot;img&amp;quot;).each(function(n, img) {
        if (img.src.indexOf(&amp;quot;gif&amp;quot;) &amp;gt;= 0 || img.width &amp;lt; 64 || img.height &amp;lt; 64)
            return;
        proxiedAjax({
            url: &amp;quot;http://detectface.com/api/detect&amp;quot;,
            data: { url: img.src },
            success: function (data) {
                if (!data || !data.faces.face)
                    return;
                var faces = data.faces.face instanceof Array ?
                            data.faces.face: [data.faces.face];
                var canvas = $(&amp;quot;&amp;lt;canvas/&amp;gt;&amp;quot;)
                    .css({
                        width: img.width + &amp;quot;px&amp;quot;,
                        height: img.height + &amp;quot;px&amp;quot;
                    })
                    .attr({ width: img.width, height: img.height });
                var ctx = canvas.get()[0].getContext(&amp;quot;2d&amp;quot;);
                $.each(faces, function(n, face) {
                    var l = makeInt(face[&amp;quot;left-eye&amp;quot;]), r = makeInt(face[&amp;quot;right-eye&amp;quot;]);
                    var vx = l.x - r.x, vy = l.y - r.y;
                    var distance = Math.sqrt(vx * vx + vy * vy);
                    var nvx = vx / distance, nvy = vy / distance;
                    ctx.drawImage(img, 0, 0);
                    ctx.strokeStyle = &amp;quot;#000&amp;quot;;
                    ctx.lineWidth = distance / 3.5;
                    ctx.lineCap = &amp;quot;butt&amp;quot;;
                    ctx.beginPath();
                    var d = distance / 4;
                    ctx.moveTo(l.x + nvx * d, l.y + nvy * d);
                    ctx.lineTo(r.x - nvx * d, r.y - nvy * d);
                    ctx.stroke();
                });
                canvas.appendTo(img.parentNode);
                $(img).remove();
            }
        });
    });
};

main();
})();&lt;/pre&gt;</content:encoded>
  </item>
  <item rdf:about="https://let.hatelabo.jp/moriyoshi/let/gYC-xqCk9YbnUg">
    <link>https://let.hatelabo.jp/moriyoshi/let/gYC-xqCk9YbnUg</link>
    <dc:date>2010-06-04T09:33:14Z</dc:date>
    <description>漢のSQL</description>
    <dc:creator>moriyoshi</dc:creator>
    <title>[Let] 漢のSQL</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2Fmoriyoshi%2Flet%2FgYC-xqCk9YbnUg.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;漢のSQL&lt;/a&gt;&lt;pre&gt;/*
 * @title 漢のSQL
 * @description 漢のSQL
 * @include http://nippondanji.blogspot.com/
 * @license MIT License
 * @require 
 */
(function(d,l,i,j,z){l=d.getElementsByTagName(&amp;quot;*&amp;quot;);for(i=l.length;--i&amp;gt;=0;)for(z=l[i].childNodes,j=z.length;--j&amp;gt;=0;)z[j].nodeType==3&amp;amp;&amp;amp;(z[j].nodeValue=z[j].nodeValue.replace(/MySQL/g,&amp;quot;俺のSQL&amp;quot;))})(document)
&lt;/pre&gt;</content:encoded>
  </item>
  <item rdf:about="https://let.hatelabo.jp/moriyoshi/let/gYC-xpWhwP_eQg">
    <link>https://let.hatelabo.jp/moriyoshi/let/gYC-xpWhwP_eQg</link>
    <dc:date>2010-05-18T08:19:42Z</dc:date>
    <description>{{{mml:CDEFG}}} のような記述が現在表示中のページにあるとき、CDEFG の部分を MML で記述された楽曲として再生。";" でパート区切り。</description>
    <dc:creator>moriyoshi</dc:creator>
    <title>[Let] MML play</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2Fmoriyoshi%2Flet%2FgYC-xpWhwP_eQg.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;MML play&lt;/a&gt;&lt;pre&gt;/*
 * @title MML play
 * @description {{{mml:CDEFG}}} のような記述が現在表示中のページにあるとき、CDEFG の部分を MML で記述された楽曲として再生。&amp;quot;;&amp;quot; でパート区切り。
 * @include http://*
 * @license MIT License
 */

(function() {
    var SoundPlayer = function() { this.initialize.apply(this, arguments); };
    SoundPlayer.packToUInt32LE = function(l) {
        var f = String.fromCharCode;
        return f(l &amp;amp; 255) + f((l &amp;gt;&amp;gt; 8) &amp;amp; 255) + f((l &amp;gt;&amp;gt; 16) &amp;amp; 255) + f((l &amp;gt;&amp;gt; 24) &amp;amp; 255);
    };

    SoundPlayer.prototype = {
        resolution: 0,

        initialize: function(resolution) {
            this.resolution = resolution;
        },

        generateWavURI: function(sounds) {
            var len = 0;
            for (var i = sounds.length; --i &amp;gt;= 0;)
                len = Math.max(len, sounds[i].length);

            var da;
            var res = SoundPlayer.packToUInt32LE(this.resolution);
            da = [
                    &amp;quot;RIFF&amp;quot; + SoundPlayer.packToUInt32LE(len + 36),
                    &amp;quot;WAVEfmt\x20\x10\x00\x00\x00\x01\x00\x01\x00&amp;quot;,
                    res, res, &amp;quot;\x01\x00\x08\x00data&amp;quot;,
                    SoundPlayer.packToUInt32LE(len)
            ];

            for (var i = 0; i &amp;lt; len; ++i) {
                var v = 0;
                for (var j = sounds.length, d; --j &amp;gt;= 0;) {
                    var n = sounds[j][i];
                    v += n ? n: 0.;
                }
                v = (v &amp;lt; -1 ? -1: (v &amp;gt;= .9 ? .9: v)) * 128 + 128;
                da.push(String.fromCharCode(v));
            }
            return &amp;quot;data:audio/wav,&amp;quot; + escape(da.join(&amp;quot;&amp;quot;));
        },

        play: function() {
            var d = this.generateWavURI(arguments);
            var n = document.createElement(&amp;quot;audio&amp;quot;);
            n.style.position = &amp;quot;absolute&amp;quot;;
            n.style.left = &amp;quot;-1000px&amp;quot;;
            document.body.appendChild(n);
            n.setAttribute(&amp;quot;src&amp;quot;, d);
            n.play();
        }
    };

    var SoundGenerator = function() { this.initialize.apply(this, arguments); };
    SoundGenerator.prototype = {
        data: null,
        resolution: null,
        envelopeGenerator: function(t) { return 1; },
        filter: null,

        initialize: function(resolution) {
            this.data = [];
            this.resolution = resolution;
        },

        generateSquareWave: function(freq, duration, vol) {
            var t = 0, d = this.data, res = this.resolution,
                eg = this.envelopeGenerator, f = this.filter, o = d.length,
                p = freq / res;
            var sin = Math.sin, pi = Math.PI;
            d[o + duration - 1] = 0;
            if (f != null) {
                f.reset();
                for (var pv = 0; t &amp;lt; duration; ++t, pv = v) {
                    var m = 2 * pi * t * p, v = pv;
                    for (var i = (0.5 / p) | 1; (i -= 2) &amp;gt; 0;)
                        v += sin(m * i) / i;
                    v /= 2;
                    d[o + t] = f.apply(4 * v * eg(t) * vol / pi);
                }
            } else {
                for (var pv = 0; t &amp;lt; duration; ++t, pv = v) {
                    var m = 2 * pi * t * p, v = pv;
                    for (var i = (0.5 / p) | 1; (i -= 2) &amp;gt; 0;)
                        v += sin(m * i) / i;
                    v /= 2;
                    d[o + t] = (4 * v * eg(t) * vol / pi);
                }
            }
        },

        generateSawWave: function(freq, duration, vol) {
            var t = 0, d = this.data, res = this.resolution,
                eg = this.envelopeGenerator, f = this.filter,
                o = d.length, p = freq / res
            d[o + duration - 1] = 0;
            var sin = Math.sin, pi = Math.PI;
            if (f != null) {
                f.reset();
                for (var pv = 0; t &amp;lt; duration; ++t, pv = v) {
                    var m = pi * t * p, v = pv;
                    for (var i = (0.5 / p) | 0; --i &amp;gt; 0; )
                        v += sin(2 * i * m) / i;
                    v /= 2;
                    d[o + t] = f.apply(2 * v * eg(t) * vol / pi);
                }
            } else {
                for (var pv = 0; t &amp;lt; duration; ++t, pv = v) {
                    var m = pi * t * p, v = pv;
                    for (var i = (0.5 / p) | 0; --i &amp;gt; 0; )
                        v += sin(2 * i * m) / i;
                    v /= 2;
                    d[o + t] = (2 * v * eg(t) * vol / pi);
                }
            }
        },

        generateSilence: function(duration) {
            var d = this.data, j;
            d[d.length + duration - 1] = 0;
        }
    };

    var MusicBuilder = function() { this.initialize.apply(this, arguments); };
    MusicBuilder.prototype = {
        initialize: function(sg) {
            this.sg = sg;
            this.tempo_ = 120;
            this.volume_ = .8;
            this.tone_ = 'square';
            this.initializeTone();
        },

        initializeTone: function() {
            var self = this;
            switch (this.tone_) {
            case 'saw':
                this.sound = function(freq, duration) {
                    this.sg.generateSawWave(freq, duration, self.volume_);
                };
                break;
            case 'square':
                this.sound = function(freq, duration) {
                    this.sg.generateSquareWave(freq, duration, self.volume_);
                };
                break;
            }
        },

        calculateDuration: function(len) {
            return (this.sg.resolution * 240 / this.tempo_) / len;
        },

        tone: function(v) {
            this.tone_ = v;
            this.initializeTone();
        },

        tempo: function(v) {
            this.tempo_ = v;
        },

        volume: function(v) {
            this.volume_ = v / 256;
        },

        note: function(n, len) {
            var f = 55 &amp;lt;&amp;lt; (n / 12);
            f *= Math.pow(2, (n % 12) / 12);
            this.sound(f, this.calculateDuration(len));
        },

        rest: function(len) {
            this.sg.generateSilence(this.calculateDuration(len));
        },

        envelope: function(eg) {
            this.sg.envelopeGenerator = eg;
        },

        parseMML: function(mml) {
            var regex = /([&amp;gt;&amp;lt;])|([LMOSTVS@])\s*(\d*)|([ABCDEFG]([#+-]?)|R)\s*(?:(\d+)\s*|(\.+)\s*){0,2}|\s+/gi;
            var m;
            var pitch_base = 36, default_len = 4;
            var syntax_error = { message: &amp;quot;Syntax error&amp;quot; };
            var invalid_parameter = { message: &amp;quot;Invalid parameter&amp;quot; };
            var pitch_table = {
                &amp;quot;a&amp;quot;:  0, &amp;quot;A&amp;quot;:  0,
                &amp;quot;b&amp;quot;:  2, &amp;quot;B&amp;quot;:  2,
                &amp;quot;c&amp;quot;: -9, &amp;quot;C&amp;quot;: -9,
                &amp;quot;d&amp;quot;: -7, &amp;quot;D&amp;quot;: -7,
                &amp;quot;e&amp;quot;: -5, &amp;quot;E&amp;quot;: -5,
                &amp;quot;f&amp;quot;: -4, &amp;quot;F&amp;quot;: -4,
                &amp;quot;g&amp;quot;: -2, &amp;quot;G&amp;quot;: -2
            };
            var envelope_cycle = 1000;
            var envelopes = [
                function(t) { return 1; },
                function(t) { return Math.max(0, 1 - t / envelope_cycle); },
                function(t) { return Math.min(1, t / envelope_cycle); },
                function(t) { return 1 - (t % envelope_cycle) / envelope_cycle; },
                function(t) { return (t % envelope_cycle) / envelope_cycle; },
                function(t) { return Math.abs((t % (envelope_cycle * 2)) - envelope_cycle) / envelope_cycle; },
                function(t) { return 1 - Math.abs((t % (envelope_cycle * 2)) - envelope_cycle) / envelope_cycle; },
                function(t) { return t &amp;lt; envelope_cycle ? 1 - t / envelope_cycle: 1; },
                function(t) { return t &amp;lt; envelope_cycle ? t / envelope_cycle: 0; }
            ];

            var envelope_table = [
                envelopes[0],
                envelopes[1],
                envelopes[1],
                envelopes[1],
                envelopes[8],
                envelopes[8],
                envelopes[8],
                envelopes[8],
                envelopes[3],
                envelopes[1],
                envelopes[5],
                envelopes[7],
                envelopes[4],
                envelopes[2],
                envelopes[6],
                envelopes[8]
            ];

            tone_table = [ 'square', 'saw' ];
            while (m = regex.exec(mml)) {
                switch (m[1]) {
                case &amp;quot;&amp;lt;&amp;quot;:
                    pitch_base += 12;
                    continue;
                case &amp;quot;&amp;gt;&amp;quot;:
                    pitch_base -= 12;
                    continue;
                }
                if (m[2]) {
                    var param = m[3] == '' ? -1: parseInt(m[3]);
                    switch (m[2]) {
                    case &amp;quot;l&amp;quot;: case &amp;quot;L&amp;quot;:
                        if (param &amp;lt; 0)
                            throw syntax_error;
                        default_len = param;
                        break;
                    case &amp;quot;o&amp;quot;: case &amp;quot;O&amp;quot;:
                        if (param &amp;lt; 0)
                            throw syntax_error;
                        pitch_base = (param - 1) * 12;
                        break;
                    case &amp;quot;t&amp;quot;: case &amp;quot;T&amp;quot;:
                        if (param &amp;lt; 0)
                            throw syntax_error;
                        this.tempo(param);
                        break;
                    case &amp;quot;v&amp;quot;: case &amp;quot;V&amp;quot;:
                        if (param &amp;lt; 0 || param &amp;gt; 255)
                            throw syntax_error;
                        this.volume(param);
                        break;
                    case 's': case 'S':
                        if (param &amp;lt; 0)
                            throw syntax_error;
                        if (param &amp;gt;= envelope_table.length)
                            throw invalid_parameter; 
                        this.envelope(envelope_table[param]);
                        break;
                    case 'm': case 'M':
                        if (param &amp;lt; 0)
                            throw syntax_error;
                        if (param &amp;lt; 1)
                            throw invalid_parameter;
                        envelope_cycle = this.sg.resolution * param / 8000;
                        break;
                    case '@':
                        if (param &amp;lt; 0)
                            throw syntax_error;
                        if (param &amp;gt;= tone_table.length)
                            throw invalid_parameter; 
                        this.tone(tone_table[param]);
                    }
                    continue;
                }
                var l = typeof(m[6]) == 'undefined' ? default_len: parseInt(m[6]),
                    a = typeof(m[7]) == 'undefined' ? 0: m[7].length,
                    d = l * (1 &amp;lt;&amp;lt; a) / ((1 &amp;lt;&amp;lt; (a + 1)) - 1);
                if (m[4]) {
                    this.note(pitch_base + pitch_table[m[4].charAt(0)]
                        + (m[5] ? (&amp;quot;#+&amp;quot;.indexOf(m[5]) &amp;lt; 0 ? -1: 1): 0), d);
                } else {
                    this.rest(d);
                }
            }
        }
    };

    var getAllTextsInElement = function(tag) {
        var retval = [];
        var traverse = function(tag) {
            if (tag.localName == &amp;quot;input&amp;quot;) {
                retval.push(tag.value);
                return;
            } else if (tag.localName == &amp;quot;textarea&amp;quot;) {
                retval.push(tag.value);
                return;
            }
            var children = tag.childNodes;
            for (var i = 0; i &amp;lt; children.length; i++) {
                var child = children.item(i);
                switch (child.nodeType) {
                case 1:
                    traverse(child);
                    break;
                case 3:
                    if (child.nodeValue)
                        retval.push(child.nodeValue);
                    break;
                }
            }
        };
        traverse(tag);
        return retval;
    };

    var text = getAllTextsInElement(document);
    var m = null;
    for (var i = 0; i &amp;lt; text.length; i++) {
        m = text[i].match(/\{\{\{mml:([^}]+)\}\}\}/i);
        if (m)
            break;
    }
    if (m) {
        var mmls = m[1].split(/\s*(?:\r|\n|\r\n|;)\s*/i);
        var s = [];
        for (var i = 0; i &amp;lt; mmls.length; ++i) {
            if (mmls[i] == '')
              continue;
            var m = new MusicBuilder(new SoundGenerator(16000));
            m.parseMML(mmls[i]);
            s.push(m.sg.data);
        }
        var sp = new SoundPlayer(16000);
        sp.play.apply(sp, s);
    }
})();

&lt;/pre&gt;</content:encoded>
  </item>
</rdf:RDF>
