plumo 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +1 -0
- data/Rakefile +10 -0
- data/bin/plumo-reloader +43 -0
- data/lib/plumo/plumo.rb +196 -0
- data/lib/plumo/public/index.html +43 -0
- data/lib/plumo/public/plumo.js +164 -0
- data/lib/plumo/version.rb +3 -0
- data/plumo.gemspec +27 -0
- data/sample_1.rb +50 -0
- metadata +83 -0
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: d9a765709e5fe89c6026a19a017c94aac11c5f990e086002a5d83d856a19524a
         | 
| 4 | 
            +
              data.tar.gz: f209c5807a9bacb2e0a4292f40f8be7aa46471fb998b5463b2a0f9f363574857
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: 8d5a123b92fc2c152c015343247a078b602af9b61cb8add276425f728bc7f1ad8e122b25eeb0ee82f15687daaa2adcbee835ca67068509f9e70dbfb3fd10b885
         | 
| 7 | 
            +
              data.tar.gz: 8afa3b523d58b2aa3707530f4f721bba34050e36a8144ade70c6e80fb5815a9ebafde4b0af269e55599358435f87ee45b0f84a3c8c4488b00b85a7a549c0a46c
         | 
    
        data/.gitignore
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE
    ADDED
    
    | @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            BSD 2-Clause License
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Copyright (c) 2019, sonota88
         | 
| 4 | 
            +
            All rights reserved.
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Redistribution and use in source and binary forms, with or without
         | 
| 7 | 
            +
            modification, are permitted provided that the following conditions are met:
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            1. Redistributions of source code must retain the above copyright notice, this
         | 
| 10 | 
            +
               list of conditions and the following disclaimer.
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            2. Redistributions in binary form must reproduce the above copyright notice,
         | 
| 13 | 
            +
               this list of conditions and the following disclaimer in the documentation
         | 
| 14 | 
            +
               and/or other materials provided with the distribution.
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
         | 
| 17 | 
            +
            AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
         | 
| 18 | 
            +
            IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
         | 
| 19 | 
            +
            DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
         | 
| 20 | 
            +
            FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
         | 
| 21 | 
            +
            DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
         | 
| 22 | 
            +
            SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
         | 
| 23 | 
            +
            CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
         | 
| 24 | 
            +
            OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
         | 
| 25 | 
            +
            OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         | 
    
        data/README.md
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            TODO
         | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/plumo-reloader
    ADDED
    
    | @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            $script_path = ARGV[0]
         | 
| 4 | 
            +
            $updated_at = Time.now
         | 
| 5 | 
            +
            $status = :running
         | 
| 6 | 
            +
            $child_pid = nil
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            def kill_child
         | 
| 9 | 
            +
              puts "kill"
         | 
| 10 | 
            +
              Process.kill :INT, $child_pid
         | 
| 11 | 
            +
              Process.waitpid $child_pid
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            def main
         | 
| 15 | 
            +
              puts "spawn"
         | 
| 16 | 
            +
              $child_pid = spawn "ruby #{$script_path}"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              while $status == :running
         | 
| 19 | 
            +
                t = File.stat($script_path).mtime
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                if $updated_at < t
         | 
| 22 | 
            +
                  puts "changed"
         | 
| 23 | 
            +
                  $updated_at = t
         | 
| 24 | 
            +
                  kill_child
         | 
| 25 | 
            +
                  break
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                sleep 1
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            Signal.trap(:INT) do
         | 
| 33 | 
            +
              $status = :stop
         | 
| 34 | 
            +
              kill_child
         | 
| 35 | 
            +
            end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            begin
         | 
| 38 | 
            +
              while $status == :running
         | 
| 39 | 
            +
                main
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            rescue => e
         | 
| 42 | 
            +
              p e
         | 
| 43 | 
            +
            end
         | 
    
        data/lib/plumo/plumo.rb
    ADDED
    
    | @@ -0,0 +1,196 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'webrick'
         | 
| 4 | 
            +
            require 'cgi'
         | 
| 5 | 
            +
            require 'json'
         | 
| 6 | 
            +
            require 'pp'
         | 
| 7 | 
            +
            require 'timeout'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class Plumo
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              class NullLogger
         | 
| 12 | 
            +
                def <<(arg)
         | 
| 13 | 
            +
                  ;
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def initialize(w, h, opts={})
         | 
| 18 | 
            +
                @w = w
         | 
| 19 | 
            +
                @h = h
         | 
| 20 | 
            +
                @session_id = nil
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                default_opts = {
         | 
| 23 | 
            +
                  port: 9080,
         | 
| 24 | 
            +
                  num_deq_max: 100
         | 
| 25 | 
            +
                }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                @opts = default_opts.merge(opts)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                @q = Thread::SizedQueue.new(100)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                @close_q = Thread::Queue.new
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                @status = :starting
         | 
| 34 | 
            +
                @server = nil
         | 
| 35 | 
            +
                @server_thread = nil
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def enq_reset
         | 
| 39 | 
            +
                @q.clear
         | 
| 40 | 
            +
                @q.enq({
         | 
| 41 | 
            +
                  type: :reset,
         | 
| 42 | 
            +
                  payload: {
         | 
| 43 | 
            +
                    w: "#{@w}px",
         | 
| 44 | 
            +
                    h: "#{@h}px"
         | 
| 45 | 
            +
                  }
         | 
| 46 | 
            +
                })
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              def handle_comet(req)
         | 
| 50 | 
            +
                qsize = @q.size
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                params = CGI.parse(req.body)
         | 
| 53 | 
            +
                session_id = params["sessionid"][0]
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                if session_id != @session_id
         | 
| 56 | 
            +
                  @session_id = session_id
         | 
| 57 | 
            +
                  enq_reset
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                events = []
         | 
| 61 | 
            +
                if @q.empty?
         | 
| 62 | 
            +
                  events << @q.deq
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                loop do
         | 
| 66 | 
            +
                  break if @q.empty?
         | 
| 67 | 
            +
                  break if @opts[:num_deq_max] <= events.size
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                  events << @q.deq
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                {
         | 
| 73 | 
            +
                  events: events,
         | 
| 74 | 
            +
                  qsize: qsize,
         | 
| 75 | 
            +
                }
         | 
| 76 | 
            +
              end
         | 
| 77 | 
            +
             | 
| 78 | 
            +
              def start
         | 
| 79 | 
            +
                @status = :running
         | 
| 80 | 
            +
             | 
| 81 | 
            +
                logger_access = NullLogger.new
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                @server = WEBrick::HTTPServer.new(
         | 
| 84 | 
            +
                  DocumentRoot: File.join(__dir__, "public"),
         | 
| 85 | 
            +
                  BindAddress: '127.0.0.1',
         | 
| 86 | 
            +
                  Port: @opts[:port],
         | 
| 87 | 
            +
                  AccessLog: [
         | 
| 88 | 
            +
                    [logger_access, WEBrick::AccessLog::COMMON_LOG_FORMAT],
         | 
| 89 | 
            +
                    [logger_access, WEBrick::AccessLog::REFERER_LOG_FORMAT]
         | 
| 90 | 
            +
                  ]
         | 
| 91 | 
            +
                )
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                @server.mount_proc("/ping") do |req, res|
         | 
| 94 | 
            +
                  res.content_type = "application/json"
         | 
| 95 | 
            +
                  res.body = JSON.generate({ status: @status })
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                @server.mount_proc("/close") do |req, res|
         | 
| 99 | 
            +
                  @close_q.enq 1
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  res.content_type = "application/json"
         | 
| 102 | 
            +
                  res.body = "{}"
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                @server.mount_proc("/comet") do |req, res|
         | 
| 106 | 
            +
                  res_data = handle_comet(req)
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                  res.content_type = "application/json"
         | 
| 109 | 
            +
                  res.body = JSON.generate(res_data)
         | 
| 110 | 
            +
                end
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                Signal.trap(:INT) do
         | 
| 113 | 
            +
                  @status = :stop
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  @q.clear
         | 
| 116 | 
            +
                  @q.enq({ type: :close })
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                  begin
         | 
| 119 | 
            +
                    Timeout.timeout(1) do
         | 
| 120 | 
            +
                      @close_q.deq
         | 
| 121 | 
            +
                    end
         | 
| 122 | 
            +
                  rescue Timeout::Error
         | 
| 123 | 
            +
                    $stderr.puts "timed out"
         | 
| 124 | 
            +
                  end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                  exit
         | 
| 127 | 
            +
                end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
                @server_thread = Thread.new do
         | 
| 130 | 
            +
                  @server.start
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                sleep 0.1
         | 
| 134 | 
            +
              end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
              def draw(*cmds)
         | 
| 137 | 
            +
                if @status == :running
         | 
| 138 | 
            +
                  @q.enq({
         | 
| 139 | 
            +
                    type: :cmds,
         | 
| 140 | 
            +
                    cmds: cmds
         | 
| 141 | 
            +
                  })
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
              end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
              def line(x0, y0, x1, y1, style={})
         | 
| 146 | 
            +
                cmds = []
         | 
| 147 | 
            +
             | 
| 148 | 
            +
                if style.key?(:color)
         | 
| 149 | 
            +
                  cmds << [:strokeStyle, style[:color]]
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                cmds += [
         | 
| 153 | 
            +
                  [:beginPath],
         | 
| 154 | 
            +
                  [:moveTo, x0, y0],
         | 
| 155 | 
            +
                  [:lineTo, x1, y1],
         | 
| 156 | 
            +
                  [:stroke]
         | 
| 157 | 
            +
                ]
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                draw(*cmds)
         | 
| 160 | 
            +
              end
         | 
| 161 | 
            +
             | 
| 162 | 
            +
              def fill_rect(x, y, w, h, style={})
         | 
| 163 | 
            +
                cmds = []
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                if style.key?(:color)
         | 
| 166 | 
            +
                  cmds << [:fillStyle, style[:color]]
         | 
| 167 | 
            +
                end
         | 
| 168 | 
            +
                
         | 
| 169 | 
            +
                cmds += [
         | 
| 170 | 
            +
                  [:beginPath],
         | 
| 171 | 
            +
                  [:fillRect, x, y, w, h],
         | 
| 172 | 
            +
                ]
         | 
| 173 | 
            +
             | 
| 174 | 
            +
                draw(*cmds)
         | 
| 175 | 
            +
              end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
              def fill_circle(x, y, r, style={})
         | 
| 178 | 
            +
                cmds = []
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                if style.key?(:color)
         | 
| 181 | 
            +
                  cmds << [:fillStyle, style[:color]]
         | 
| 182 | 
            +
                end
         | 
| 183 | 
            +
                
         | 
| 184 | 
            +
                cmds += [
         | 
| 185 | 
            +
                  [:beginPath],
         | 
| 186 | 
            +
                  [:arc,
         | 
| 187 | 
            +
                   x, y,
         | 
| 188 | 
            +
                   r,
         | 
| 189 | 
            +
                   0, Math::PI * 2, false
         | 
| 190 | 
            +
                  ],
         | 
| 191 | 
            +
                  [:fill]
         | 
| 192 | 
            +
                ]
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                draw(*cmds)
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
            end
         | 
| @@ -0,0 +1,43 @@ | |
| 1 | 
            +
            <html>
         | 
| 2 | 
            +
             | 
| 3 | 
            +
              <head>
         | 
| 4 | 
            +
                <meta charset="utf-8" />
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
         | 
| 7 | 
            +
                <script src="./plumo.js"></script>
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                <style>
         | 
| 10 | 
            +
                 * {
         | 
| 11 | 
            +
                   font-family: monospace;
         | 
| 12 | 
            +
                 }
         | 
| 13 | 
            +
                </style>
         | 
| 14 | 
            +
              </head>
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              <body
         | 
| 17 | 
            +
                  style="
         | 
| 18 | 
            +
                         background: #222;
         | 
| 19 | 
            +
                         color: #ccc;
         | 
| 20 | 
            +
                         "
         | 
| 21 | 
            +
              >
         | 
| 22 | 
            +
                <div>
         | 
| 23 | 
            +
                  ping: <span id="ping"></span>
         | 
| 24 | 
            +
                </div>
         | 
| 25 | 
            +
                
         | 
| 26 | 
            +
                <div>
         | 
| 27 | 
            +
                  requests/sec: <span id="rps">-</span>
         | 
| 28 | 
            +
                </div>
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                <div>
         | 
| 31 | 
            +
                  queue size: <span id="qsize">-</span>
         | 
| 32 | 
            +
                  <pre
         | 
| 33 | 
            +
                      id="qsize_bar"
         | 
| 34 | 
            +
                      style="font-size: 40%;"> </pre>
         | 
| 35 | 
            +
                </div>
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                <canvas
         | 
| 38 | 
            +
                    width="100px" height="100px"
         | 
| 39 | 
            +
                    style="border: solid 1px #000;"
         | 
| 40 | 
            +
                />
         | 
| 41 | 
            +
              </body>
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            </html>
         | 
| @@ -0,0 +1,164 @@ | |
| 1 | 
            +
            const puts = (...args)=>{
         | 
| 2 | 
            +
              console.log(...args);
         | 
| 3 | 
            +
            };
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            class Comet {
         | 
| 6 | 
            +
              constructor(){
         | 
| 7 | 
            +
                this.timer = null;
         | 
| 8 | 
            +
                this.connected = true;
         | 
| 9 | 
            +
                this.sessionId = new Date().getTime();
         | 
| 10 | 
            +
              }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              _open(){
         | 
| 13 | 
            +
                $.post("/comet", { sessionid: this.sessionId })
         | 
| 14 | 
            +
                  .then((data)=>{
         | 
| 15 | 
            +
                    if (this.connected) {
         | 
| 16 | 
            +
                      this.onmessage(data);
         | 
| 17 | 
            +
                      this.open();
         | 
| 18 | 
            +
                    }
         | 
| 19 | 
            +
                  })
         | 
| 20 | 
            +
                  .catch((...args)=>{
         | 
| 21 | 
            +
                    if (this.connected) {
         | 
| 22 | 
            +
                      console.info("comet > catch", args);
         | 
| 23 | 
            +
                    } else {
         | 
| 24 | 
            +
                      // ignore
         | 
| 25 | 
            +
                    }
         | 
| 26 | 
            +
                  });
         | 
| 27 | 
            +
              }
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              open(){
         | 
| 30 | 
            +
                clearTimeout(this.timer);
         | 
| 31 | 
            +
                this.timer = setTimeout(()=>{
         | 
| 32 | 
            +
                  this._open();
         | 
| 33 | 
            +
                }, 0);
         | 
| 34 | 
            +
              }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              onclose(){
         | 
| 37 | 
            +
                this.connected = false;
         | 
| 38 | 
            +
                console.info("onclose");
         | 
| 39 | 
            +
                $.post("/close");
         | 
| 40 | 
            +
                clearTimeout(this.timer);
         | 
| 41 | 
            +
              }
         | 
| 42 | 
            +
            }
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            class CanvasWrapper {
         | 
| 45 | 
            +
              constructor(el){
         | 
| 46 | 
            +
                this.el = el;
         | 
| 47 | 
            +
                this.$el = $(el);
         | 
| 48 | 
            +
                this.ctx = el.getContext("2d");
         | 
| 49 | 
            +
              }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              reset(w, h){
         | 
| 52 | 
            +
                this.$el.attr("width" , w);
         | 
| 53 | 
            +
                this.$el.attr("height", h);
         | 
| 54 | 
            +
                this.$el.show();
         | 
| 55 | 
            +
              }
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              execCmd(cmd){
         | 
| 58 | 
            +
                const _cmd  = cmd[0];
         | 
| 59 | 
            +
                const args = cmd.slice(1);
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                if (_cmd in this.ctx) {
         | 
| 62 | 
            +
                  if (typeof this.ctx[_cmd] === "function") {
         | 
| 63 | 
            +
                    this.ctx[_cmd](...args);
         | 
| 64 | 
            +
                  } else {
         | 
| 65 | 
            +
                    this.ctx[_cmd] = args[0];
         | 
| 66 | 
            +
                  }
         | 
| 67 | 
            +
                } else {
         | 
| 68 | 
            +
                  console.error("invalid command", _cmd);
         | 
| 69 | 
            +
                }
         | 
| 70 | 
            +
              }
         | 
| 71 | 
            +
            }
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            class App {
         | 
| 74 | 
            +
              constructor(){
         | 
| 75 | 
            +
                this.comet = new Comet();
         | 
| 76 | 
            +
                this.cw = new CanvasWrapper($("canvas").get(0));
         | 
| 77 | 
            +
                this.resTimes = [];
         | 
| 78 | 
            +
              }
         | 
| 79 | 
            +
             | 
| 80 | 
            +
              start(){
         | 
| 81 | 
            +
                // comet
         | 
| 82 | 
            +
                this.comet.onmessage = this.onmessage.bind(this);
         | 
| 83 | 
            +
                this.comet.open();
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                // ping thread
         | 
| 86 | 
            +
                setInterval(()=>{
         | 
| 87 | 
            +
                  this.ping();
         | 
| 88 | 
            +
                }, 1000);
         | 
| 89 | 
            +
              }
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              onmessage(data){
         | 
| 92 | 
            +
                this.refreshRps();
         | 
| 93 | 
            +
                this.refreshQsize(data.qsize, data.events.length);
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                data.events.forEach((event)=>{
         | 
| 96 | 
            +
                  switch (event.type) {
         | 
| 97 | 
            +
                  case "reset":
         | 
| 98 | 
            +
                    this.cw.reset(event.payload.w, event.payload.h);
         | 
| 99 | 
            +
                    break;
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                  case "cmds":
         | 
| 102 | 
            +
                    event.cmds.forEach((cmd)=>{
         | 
| 103 | 
            +
                      this.cw.execCmd(cmd);
         | 
| 104 | 
            +
                    });
         | 
| 105 | 
            +
                    break;
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                  case "close":
         | 
| 108 | 
            +
                    this.comet.onclose();
         | 
| 109 | 
            +
                    break;
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  default:
         | 
| 112 | 
            +
                    console.error("unknown event", event);
         | 
| 113 | 
            +
                  }
         | 
| 114 | 
            +
                });
         | 
| 115 | 
            +
              }
         | 
| 116 | 
            +
             | 
| 117 | 
            +
              refreshRps(){
         | 
| 118 | 
            +
                const currentTime = new Date().getTime();
         | 
| 119 | 
            +
                this.resTimes.push(currentTime);
         | 
| 120 | 
            +
                const limit = currentTime - 1000;
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                const recent =
         | 
| 123 | 
            +
                  this.resTimes.filter((time)=> limit <= time );
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                this.resTimes = recent;
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                $("#rps").text(recent.length);
         | 
| 128 | 
            +
              }
         | 
| 129 | 
            +
             | 
| 130 | 
            +
              refreshQsize(qsize, numEvents){
         | 
| 131 | 
            +
                $("#qsize").text(qsize);
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                let qsizeBar = "#".repeat(numEvents);
         | 
| 134 | 
            +
                if (numEvents < qsize) {
         | 
| 135 | 
            +
                  qsizeBar += "-".repeat(qsize - numEvents);
         | 
| 136 | 
            +
                }
         | 
| 137 | 
            +
                $("#qsize_bar").text(qsizeBar);
         | 
| 138 | 
            +
              }
         | 
| 139 | 
            +
             | 
| 140 | 
            +
              ping(){
         | 
| 141 | 
            +
                if (this.comet.connected) {
         | 
| 142 | 
            +
                  return;
         | 
| 143 | 
            +
                }
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                $.post("/ping")
         | 
| 146 | 
            +
                .then((data)=>{
         | 
| 147 | 
            +
                  if (data.status === "running") {
         | 
| 148 | 
            +
                    location.reload();
         | 
| 149 | 
            +
                  } else {
         | 
| 150 | 
            +
                    console.info("ping > " + data.status);
         | 
| 151 | 
            +
                    throw new Error("ping ng");
         | 
| 152 | 
            +
                  }
         | 
| 153 | 
            +
                })
         | 
| 154 | 
            +
                .catch(()=>{
         | 
| 155 | 
            +
                  const text = $("#ping").text();
         | 
| 156 | 
            +
                  $("#ping").text(text + ".");
         | 
| 157 | 
            +
                });
         | 
| 158 | 
            +
              }
         | 
| 159 | 
            +
            }
         | 
| 160 | 
            +
             | 
| 161 | 
            +
            $(()=>{
         | 
| 162 | 
            +
              const app = new App();
         | 
| 163 | 
            +
              app.start();
         | 
| 164 | 
            +
            });
         | 
    
        data/plumo.gemspec
    ADDED
    
    | @@ -0,0 +1,27 @@ | |
| 1 | 
            +
            # coding: utf-8
         | 
| 2 | 
            +
            lib = File.expand_path('../lib', __FILE__)
         | 
| 3 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 4 | 
            +
            require 'plumo/version'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Gem::Specification.new do |spec|
         | 
| 7 | 
            +
              spec.name          = "plumo"
         | 
| 8 | 
            +
              spec.version       = Plumo::VERSION
         | 
| 9 | 
            +
              spec.authors       = ["sonota88"]
         | 
| 10 | 
            +
              spec.email         = ["yosiot8753@gmail.com"]
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              spec.summary       = %q{Easy 2d-graphincs using Ruby and Canvas}
         | 
| 13 | 
            +
              spec.description   = %q{Easy 2d-graphincs using Ruby and Canvas}
         | 
| 14 | 
            +
              spec.homepage      = "https://github.com/sonota88/plumo"
         | 
| 15 | 
            +
              spec.license       = 'BSD 2-Clause "Simplified"'
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              spec.files         = `git ls-files -z`.split("\x0").reject do |f|
         | 
| 18 | 
            +
                f.match(%r{^(test|spec|features)/})
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
              spec.bindir        = "exe"
         | 
| 21 | 
            +
              spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
         | 
| 22 | 
            +
              spec.require_paths = ["lib"]
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              spec.add_development_dependency "bundler", "~> 1.17"
         | 
| 25 | 
            +
              spec.add_development_dependency "rake", "~> 12.0"
         | 
| 26 | 
            +
              # spec.add_development_dependency "minitest", "~> 5.0"
         | 
| 27 | 
            +
            end
         | 
    
        data/sample_1.rb
    ADDED
    
    | @@ -0,0 +1,50 @@ | |
| 1 | 
            +
            $LOAD_PATH.unshift './lib/plumo'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'plumo'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            def rand_color
         | 
| 6 | 
            +
              "rgba(%f, %f, %f, %f)" % [
         | 
| 7 | 
            +
                rand * 240,
         | 
| 8 | 
            +
                rand * 200,
         | 
| 9 | 
            +
                rand * 120,
         | 
| 10 | 
            +
                0.5 + rand / 2
         | 
| 11 | 
            +
               ]
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            def rand_x
         | 
| 15 | 
            +
              rand * $canvas_w
         | 
| 16 | 
            +
            end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            def rand_y
         | 
| 19 | 
            +
              rand * $canvas_h
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            # --------------------------------
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            $canvas_w = 400
         | 
| 25 | 
            +
            $canvas_h = 200
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            plumo = Plumo.new($canvas_w, $canvas_h)
         | 
| 28 | 
            +
            plumo.start
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            loop do
         | 
| 31 | 
            +
              plumo.line(
         | 
| 32 | 
            +
                rand_x, rand_y,
         | 
| 33 | 
            +
                rand_x, rand_y,
         | 
| 34 | 
            +
                color: rand_color
         | 
| 35 | 
            +
              )
         | 
| 36 | 
            +
             | 
| 37 | 
            +
              plumo.fill_circle(
         | 
| 38 | 
            +
                rand_x, rand_y, rand * 50,
         | 
| 39 | 
            +
                color: rand_color
         | 
| 40 | 
            +
              )
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              width = rand * 50
         | 
| 43 | 
            +
              plumo.fill_rect(
         | 
| 44 | 
            +
                rand_x, rand_y,
         | 
| 45 | 
            +
                width, width,
         | 
| 46 | 
            +
                color: rand_color
         | 
| 47 | 
            +
              )
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              sleep 0.1
         | 
| 50 | 
            +
            end
         | 
    
        metadata
    ADDED
    
    | @@ -0,0 +1,83 @@ | |
| 1 | 
            +
            --- !ruby/object:Gem::Specification
         | 
| 2 | 
            +
            name: plumo
         | 
| 3 | 
            +
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            +
              version: 0.0.1
         | 
| 5 | 
            +
            platform: ruby
         | 
| 6 | 
            +
            authors:
         | 
| 7 | 
            +
            - sonota88
         | 
| 8 | 
            +
            autorequire: 
         | 
| 9 | 
            +
            bindir: exe
         | 
| 10 | 
            +
            cert_chain: []
         | 
| 11 | 
            +
            date: 2019-04-14 00:00:00.000000000 Z
         | 
| 12 | 
            +
            dependencies:
         | 
| 13 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 14 | 
            +
              name: bundler
         | 
| 15 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 | 
            +
                requirements:
         | 
| 17 | 
            +
                - - "~>"
         | 
| 18 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 19 | 
            +
                    version: '1.17'
         | 
| 20 | 
            +
              type: :development
         | 
| 21 | 
            +
              prerelease: false
         | 
| 22 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 | 
            +
                requirements:
         | 
| 24 | 
            +
                - - "~>"
         | 
| 25 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 26 | 
            +
                    version: '1.17'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: rake
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - "~>"
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '12.0'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - "~>"
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '12.0'
         | 
| 41 | 
            +
            description: Easy 2d-graphincs using Ruby and Canvas
         | 
| 42 | 
            +
            email:
         | 
| 43 | 
            +
            - yosiot8753@gmail.com
         | 
| 44 | 
            +
            executables: []
         | 
| 45 | 
            +
            extensions: []
         | 
| 46 | 
            +
            extra_rdoc_files: []
         | 
| 47 | 
            +
            files:
         | 
| 48 | 
            +
            - ".gitignore"
         | 
| 49 | 
            +
            - Gemfile
         | 
| 50 | 
            +
            - LICENSE
         | 
| 51 | 
            +
            - README.md
         | 
| 52 | 
            +
            - Rakefile
         | 
| 53 | 
            +
            - bin/plumo-reloader
         | 
| 54 | 
            +
            - lib/plumo/plumo.rb
         | 
| 55 | 
            +
            - lib/plumo/public/index.html
         | 
| 56 | 
            +
            - lib/plumo/public/plumo.js
         | 
| 57 | 
            +
            - lib/plumo/version.rb
         | 
| 58 | 
            +
            - plumo.gemspec
         | 
| 59 | 
            +
            - sample_1.rb
         | 
| 60 | 
            +
            homepage: https://github.com/sonota88/plumo
         | 
| 61 | 
            +
            licenses:
         | 
| 62 | 
            +
            - BSD 2-Clause "Simplified"
         | 
| 63 | 
            +
            metadata: {}
         | 
| 64 | 
            +
            post_install_message: 
         | 
| 65 | 
            +
            rdoc_options: []
         | 
| 66 | 
            +
            require_paths:
         | 
| 67 | 
            +
            - lib
         | 
| 68 | 
            +
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 69 | 
            +
              requirements:
         | 
| 70 | 
            +
              - - ">="
         | 
| 71 | 
            +
                - !ruby/object:Gem::Version
         | 
| 72 | 
            +
                  version: '0'
         | 
| 73 | 
            +
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 74 | 
            +
              requirements:
         | 
| 75 | 
            +
              - - ">="
         | 
| 76 | 
            +
                - !ruby/object:Gem::Version
         | 
| 77 | 
            +
                  version: '0'
         | 
| 78 | 
            +
            requirements: []
         | 
| 79 | 
            +
            rubygems_version: 3.0.1
         | 
| 80 | 
            +
            signing_key: 
         | 
| 81 | 
            +
            specification_version: 4
         | 
| 82 | 
            +
            summary: Easy 2d-graphincs using Ruby and Canvas
         | 
| 83 | 
            +
            test_files: []
         |