p5rb 0.0.1 → 0.0.3
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 +5 -5
- data/lib/p5rb.rb +167 -54
- data/p5rb.gemspec +3 -1
- metadata +18 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b79ebfd6c7fa06d28955e916d1dd8c40f550eac344f03b7eaf65f6281c3bed2f
|
4
|
+
data.tar.gz: f2b2555f10efd15b009e146dc232a3b947514960cb81c81487bc0c8d39e205e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5f7ccdcb0a16223887864366aeb2957adb705d8a96bbb60f51195bda826acad9e4a7a67ae925e82f5e7f35c4fdfca2641fac32eb560e8c7d01c9ae280760e008
|
7
|
+
data.tar.gz: ee31129a27f4073937c6bb5c2bdffbcc41c9b1ae29ccb425ee7d49b1bbcca391747461899544e21bd30557d0c1fa51d5f4460d5b62f410de580fa3b01909cc72
|
data/lib/p5rb.rb
CHANGED
@@ -3,87 +3,200 @@ module P5
|
|
3
3
|
attr_reader :buffer_setup
|
4
4
|
attr_reader :buffer_draw
|
5
5
|
end
|
6
|
-
|
7
|
-
|
6
|
+
@buffer_setup = []
|
7
|
+
@buffer_draw = []
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
9
|
+
module Block
|
10
|
+
class << self
|
11
|
+
attr_writer :buffer
|
12
|
+
def raw _
|
13
|
+
@buffer.push _
|
14
|
+
end
|
15
|
+
def background color
|
16
|
+
@buffer.push "background(#{color})"
|
17
|
+
end
|
18
|
+
def noStroke
|
19
|
+
@buffer.push "noStroke()"
|
20
|
+
end
|
21
|
+
def stroke color
|
22
|
+
@buffer.push "stroke(#{color})"
|
23
|
+
end
|
24
|
+
def translate x, y
|
25
|
+
@buffer.push "translate(#{x}, #{y})"
|
26
|
+
end
|
27
|
+
def line x1, y1, x2, y2
|
28
|
+
@buffer.push "line(#{x1}, #{y1}, #{x2}, #{y2})"
|
29
|
+
end
|
30
|
+
def circle x, y, r
|
31
|
+
@buffer.push "circle(#{x}, #{y}, #{r})"
|
32
|
+
end
|
33
|
+
def ellipse *args # not tested yet
|
34
|
+
@buffer.push "ellipse(#{args.join ?,})"
|
35
|
+
end
|
36
|
+
def fill color, alpha = nil
|
37
|
+
@buffer.push "fill(#{color}#{", #{alpha}" if alpha})"
|
38
|
+
end
|
39
|
+
def rect x, y, w, h, fill: nil
|
40
|
+
(@buffer.push "push()"; fill fill) if fill
|
41
|
+
@buffer.push "rect(#{x}, #{y}, #{w}, #{h})"
|
42
|
+
@buffer.push "pop()" if fill
|
43
|
+
end
|
44
|
+
def point x, y
|
45
|
+
@buffer.push "point(#{x}, #{y})"
|
46
|
+
end
|
47
|
+
def textSize size
|
48
|
+
@buffer.push "textSize(#{size})"
|
49
|
+
end
|
50
|
+
def textAlign *args
|
51
|
+
@buffer.push "textAlign(#{args.join ", "})"
|
52
|
+
end
|
53
|
+
def textWidth text
|
54
|
+
@buffer.push "textWidth(#{text.inspect})"
|
55
|
+
end
|
56
|
+
def textAscent text
|
57
|
+
@buffer.push "textAscent(#{text.inspect})"
|
58
|
+
end
|
59
|
+
def text text, x, y, fill: nil
|
60
|
+
(@buffer.push "push()"; fill fill) if fill
|
61
|
+
@buffer.push "text(#{text.inspect}, #{x}, #{y})"
|
62
|
+
@buffer.push "pop()" if fill
|
63
|
+
end
|
64
|
+
def map *args
|
65
|
+
"map(#{args.join ", "})"
|
66
|
+
end
|
50
67
|
end
|
68
|
+
end
|
51
69
|
|
70
|
+
class << self
|
52
71
|
def setup &block
|
53
|
-
|
54
|
-
|
55
|
-
@buffer = []
|
72
|
+
::P5::Block.buffer = @buffer_setup
|
73
|
+
::P5::Block.module_eval &block
|
56
74
|
end
|
57
|
-
def draw &block
|
58
|
-
|
59
|
-
|
60
|
-
@buffer = []
|
75
|
+
def draw &block # not tested yet
|
76
|
+
::P5::Block.buffer = @buffer_draw
|
77
|
+
::P5::Block.module_eval &block
|
61
78
|
end
|
79
|
+
end
|
62
80
|
|
81
|
+
class << self
|
82
|
+
def plot_scatter data, reverse_y: false
|
83
|
+
size = 1000
|
84
|
+
max = nil
|
85
|
+
(x_range, x_from, x_to, x_enum, x_f),
|
86
|
+
(y_range, y_from, y_to, y_enum, y_f) = data.transpose.map do |axis|
|
87
|
+
min, max = axis.minmax
|
88
|
+
range = (min - max).abs
|
89
|
+
division = 10**Math::log10(range).floor
|
90
|
+
from = min.div(division)*division
|
91
|
+
to = -(-max).div(division)*division
|
92
|
+
[
|
93
|
+
to - from,
|
94
|
+
from, to,
|
95
|
+
from.step(to, division),
|
96
|
+
]
|
97
|
+
end
|
98
|
+
max = [x_range, y_range].max
|
99
|
+
x_f = ->_{ 20 + (size-40.0) * (_ - x_from) / max }
|
100
|
+
y_f = ->_{ 20 + (size-40.0) * (reverse_y ? y_to - _ : _ - y_from) / max }
|
101
|
+
P5 40 + (size-40.0) * x_range / max + 50, # TODO: properly fix the issue that with wide labels the right end of the plot may be cut off
|
102
|
+
40 + (size-40.0) * y_range / max do
|
103
|
+
setup do
|
104
|
+
textSize 15
|
105
|
+
raw "const w = max([#{y_enum.map{ |_| "textWidth(#{_})" }.join ?,}])"
|
106
|
+
raw "translate(w, 15)"
|
107
|
+
stroke 200
|
108
|
+
textAlign :CENTER, :BOTTOM; x_enum.each{ |_| line x_f[_], y_f[y_from], x_f[_], y_f[y_to]; text _, x_f[_], 20-5 }
|
109
|
+
textAlign :RIGHT, :CENTER; y_enum.each{ |_| line x_f[x_from], y_f[_], x_f[x_to], y_f[_]; text _, x_f[x_from]-5, y_f[_] }
|
110
|
+
stroke 0
|
111
|
+
data.each{ |x,y| point x_f[x], y_f[y] }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
def plot_bar_grouped data
|
116
|
+
# TODO: this is currently pretty much hardcoded for a time dates charting
|
117
|
+
cls = data.values.flat_map(&:keys).uniq.sort
|
118
|
+
size = cls.size + 1
|
119
|
+
from, to = data.keys.minmax
|
120
|
+
max = data.values.flat_map(&:values).max
|
121
|
+
P5 500, 500 do
|
122
|
+
setup do
|
123
|
+
noStroke
|
124
|
+
textAlign :CENTER
|
125
|
+
cls.each_with_index{ |_, i| text _, 50+400/(size-2)*i, 25, fill: %w{ 'red' 'green' 'blue' }[i] }
|
126
|
+
textAlign :RIGHT, :TOP
|
127
|
+
(from..to).each do |date|
|
128
|
+
y = map date.ajd.to_i, from.ajd.to_i, to.ajd.to_i, 50, 450
|
129
|
+
text date.strftime("%m-%d"), 45, y
|
130
|
+
rect 50, y, map(data.fetch(date,{})[cls[0]]||0, 0, max, 0, 400), 400/(to-from)/size, fill: "'red'"
|
131
|
+
rect 50, "#{y}+#{400/(to-from)/size}", map(data.fetch(date,{})[cls[1]]||0, 0, max, 0, 400), 400/(to-from)/size, fill: "'green'"
|
132
|
+
rect 50, "#{y}+#{800/(to-from)/size}", map(data.fetch(date,{})[cls[2]]||0, 0, max, 0, 400), 400/(to-from)/size, fill: "'blue'"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
def plot_bar_stacked data, names, colorize
|
138
|
+
count = {}
|
139
|
+
max = data.map do |_, day|
|
140
|
+
day.each{ |k,v| count[k] ||= 0; count[k] += v }.map(&:last).reduce :+
|
141
|
+
end.max
|
142
|
+
pairs = {}
|
143
|
+
data.each_cons(2) do |(_, day1), (_, day2)|
|
144
|
+
(day1.map(&:first) & day2.map(&:first)).each{ |_| pairs[_] ||= 0; pairs[_] += 1 }
|
145
|
+
end
|
146
|
+
require "pcbr"
|
147
|
+
require "set"
|
148
|
+
pcbr = PCBR.new
|
149
|
+
count.max_by(colorize){ |k,v| v }.each{ |k,v| pcbr.store k, [-v, pairs[k]||0] }
|
150
|
+
top = pcbr.sorted
|
151
|
+
size = 500
|
152
|
+
P5 size, size do
|
153
|
+
setup do
|
154
|
+
noStroke
|
155
|
+
textAlign :RIGHT, :TOP
|
156
|
+
border = 25
|
157
|
+
left = "#{border} + textWidth(\"00-00 - 00-00\") + 5"
|
158
|
+
data.each_with_index do |(bin, day), i|
|
159
|
+
y1 = map i, 0, data.size, border, size-border
|
160
|
+
y2 = map i+1, 0, data.size, border, size-border
|
161
|
+
text bin, "#{left} - 5", y1
|
162
|
+
pos = 0
|
163
|
+
day.sort_by{ |k,| top.index(k) || top.size }.each do |k, v|
|
164
|
+
rect \
|
165
|
+
map(pos, 0, max, left, size-border), y1,
|
166
|
+
map(v, 0, max, 0, "#{size}-#{border}-(#{left})"), "#{y2}-#{y1}",
|
167
|
+
fill: top.include?(k) ? "color('hsl(#{(((3-Math.sqrt(5))*180 * top.index(k)) % 360).round}, 75%, 75%)')" : "color('hsl(0, 0%, 75%)')"
|
168
|
+
pos += v
|
169
|
+
end
|
170
|
+
end
|
171
|
+
top.each_with_index{ |id, i| text names[id].inspect[1..-2], size-border, "#{border} + textAscent('X') * #{i}", fill: "color('hsl(#{(((3-Math.sqrt(5))*180 * top.index(id)) % 360).round}, 75%, 75%)')" }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
63
175
|
end
|
64
176
|
end
|
65
177
|
|
66
178
|
def P5 width, height, &block
|
67
|
-
P5.module_eval &block
|
179
|
+
::P5.module_eval &block
|
68
180
|
<<~HEREDOC
|
69
181
|
<html>
|
70
182
|
<head>
|
183
|
+
<meta charset="UTF-8">
|
71
184
|
<script src="https://github.com/processing/p5.js/releases/download/v1.4.2/p5.min.js"></script>
|
72
185
|
<script>
|
73
186
|
function setup() {
|
74
187
|
createCanvas(#{width}, #{height});
|
75
188
|
#{
|
76
|
-
P5.buffer_setup.join(";\n").gsub(/^/, ?\s*
|
189
|
+
::P5.buffer_setup.join(";\n").gsub(/^/, ?\s*12)
|
77
190
|
}
|
78
191
|
}
|
79
192
|
function draw() {
|
80
193
|
#{
|
81
|
-
P5.buffer_draw.join(";\n").gsub(/^/, ?\s*
|
194
|
+
::P5.buffer_draw.join(";\n").gsub(/^/, ?\s*12)
|
82
195
|
}
|
83
196
|
}
|
84
197
|
</script>
|
85
198
|
</head>
|
86
|
-
<body><main></main></body>
|
199
|
+
<body style="margin: 0"><main></main></body>
|
87
200
|
</html>
|
88
201
|
HEREDOC
|
89
202
|
end
|
data/p5rb.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "p5rb"
|
3
|
-
spec.version = "0.0.
|
3
|
+
spec.version = "0.0.3"
|
4
4
|
spec.summary = "Ruby DSL for p5.js"
|
5
5
|
|
6
6
|
spec.author = "Victor Maslov aka Nakilon"
|
@@ -8,5 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.license = "MIT"
|
9
9
|
spec.metadata = {"source_code_uri" => "https://github.com/nakilon/p5rb"}
|
10
10
|
|
11
|
+
spec.add_dependency "pcbr"
|
12
|
+
|
11
13
|
spec.files = %w{ LICENSE p5rb.gemspec lib/p5rb.rb }
|
12
14
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: p5rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Maslov aka Nakilon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
12
|
-
dependencies:
|
11
|
+
date: 2022-12-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pcbr
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
description:
|
14
28
|
email: nakilon@gmail.com
|
15
29
|
executables: []
|
@@ -39,8 +53,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
requirements: []
|
42
|
-
|
43
|
-
rubygems_version: 2.5.2.3
|
56
|
+
rubygems_version: 3.3.25
|
44
57
|
signing_key:
|
45
58
|
specification_version: 4
|
46
59
|
summary: Ruby DSL for p5.js
|