picrate 1.3.0-java → 2.0.0.pre-java
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 +4 -4
- data/.mvn/extensions.xml +1 -1
- data/.mvn/wrapper/maven-wrapper.properties +2 -2
- data/CHANGELOG.md +2 -1
- data/Gemfile +3 -1
- data/README.md +4 -2
- data/Rakefile +8 -4
- data/bin/picrate +3 -1
- data/docs/_posts/2019-11-11-getting_started_buster.md +1 -1
- data/lib/picrate.rb +1 -1
- data/lib/picrate/app.rb +10 -3
- data/lib/picrate/creators/parameters.rb +8 -8
- data/lib/picrate/creators/sketch_factory.rb +5 -3
- data/lib/picrate/helper_methods.rb +21 -21
- data/lib/picrate/helpers/numeric.rb +2 -0
- data/lib/picrate/library.rb +5 -1
- data/lib/picrate/library_loader.rb +2 -0
- data/lib/picrate/native_folder.rb +6 -4
- data/lib/picrate/native_loader.rb +3 -0
- data/lib/picrate/runner.rb +1 -0
- data/lib/picrate/version.rb +1 -1
- data/library/boids/boids.rb +17 -8
- data/library/chooser/chooser.rb +10 -9
- data/library/color_group/color_group.rb +2 -0
- data/library/control_panel/control_panel.rb +7 -4
- data/library/dxf/dxf.rb +2 -0
- data/library/library_proxy/library_proxy.rb +2 -0
- data/library/net/net.rb +2 -0
- data/library/slider/slider.rb +24 -23
- data/library/vector_utils/vector_utils.rb +4 -0
- data/library/video_event/video_event.rb +2 -0
- data/picrate.gemspec +14 -12
- data/pom.rb +15 -15
- data/pom.xml +5 -5
- data/src/main/java/monkstone/ColorUtil.java +1 -1
- data/src/main/java/monkstone/MathToolModule.java +1 -1
- data/src/main/java/monkstone/PicrateLibrary.java +8 -8
- data/src/main/java/monkstone/fastmath/Deglut.java +16 -16
- data/src/main/java/monkstone/filechooser/Chooser.java +1 -1
- data/src/main/java/monkstone/noise/SimplexNoise.java +3 -3
- data/src/main/java/monkstone/slider/CustomHorizontalSlider.java +1 -1
- data/src/main/java/monkstone/slider/CustomVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SimpleHorizontalSlider.java +12 -12
- data/src/main/java/monkstone/slider/SimpleVerticalSlider.java +1 -1
- data/src/main/java/monkstone/slider/SliderBar.java +1 -1
- data/src/main/java/monkstone/slider/SliderGroup.java +1 -1
- data/src/main/java/monkstone/slider/WheelHandler.java +1 -1
- data/src/main/java/monkstone/vecmath/package-info.java +1 -1
- data/src/main/java/monkstone/vecmath/vec2/Vec2.java +1 -1
- data/src/main/java/monkstone/vecmath/vec3/Vec3.java +1 -1
- data/src/main/java/monkstone/videoevent/CaptureEvent.java +1 -1
- data/src/main/java/monkstone/videoevent/MovieEvent.java +1 -1
- data/src/main/java/monkstone/videoevent/package-info.java +1 -1
- data/src/main/java/processing/awt/PGraphicsJava2D.java +11 -13
- data/src/main/java/processing/awt/PSurfaceAWT.java +0 -20
- data/src/main/java/processing/core/PApplet.java +1949 -2247
- data/src/main/java/processing/core/PConstants.java +180 -180
- data/src/main/java/processing/core/PFont.java +2 -2
- data/src/main/java/processing/core/PGraphics.java +90 -90
- data/src/main/java/processing/core/PImage.java +65 -65
- data/src/main/java/processing/core/PMatrix.java +39 -39
- data/src/main/java/processing/core/PSurface.java +37 -37
- data/src/main/java/processing/core/PVector.java +2 -2
- data/src/main/java/processing/data/FloatDict.java +251 -284
- data/src/main/java/processing/data/TableRow.java +32 -32
- data/src/main/java/processing/dxf/RawDXF.java +3 -3
- data/src/main/java/processing/net/Client.java +1 -1
- data/src/main/java/processing/opengl/PGL.java +3884 -3950
- data/src/main/java/processing/opengl/PGraphicsOpenGL.java +38 -21
- data/src/main/java/processing/opengl/PSurfaceJOGL.java +42 -61
- data/test/color_group_test.rb +4 -4
- data/test/deglut_spec_test.rb +2 -0
- data/test/helper_methods_test.rb +41 -13
- data/test/math_tool_test.rb +46 -37
- data/test/respond_to_test.rb +5 -3
- data/test/sketches/key_event.rb +2 -2
- data/test/sketches/library/my_library/my_library.rb +3 -0
- data/test/test_helper.rb +2 -0
- data/test/vecmath_spec_test.rb +30 -19
- data/vendors/Rakefile +2 -2
- metadata +29 -17
@@ -30,31 +30,31 @@ public interface PSurface {
|
|
30
30
|
/**
|
31
31
|
* Minimum dimensions for the window holding an applet.
|
32
32
|
*/
|
33
|
-
|
33
|
+
int MIN_WINDOW_WIDTH = 128;
|
34
34
|
|
35
35
|
/**
|
36
36
|
*
|
37
37
|
*/
|
38
|
-
|
38
|
+
int MIN_WINDOW_HEIGHT = 128;
|
39
39
|
|
40
40
|
// renderer that doesn't draw to the screen
|
41
41
|
/**
|
42
42
|
*
|
43
43
|
* @param sketch
|
44
44
|
*/
|
45
|
-
|
45
|
+
void initOffscreen(PApplet sketch);
|
46
46
|
|
47
47
|
// considering removal in favor of separate Component classes for appropriate renderers
|
48
48
|
// (i.e. for Java2D or a generic Image surface, but not PDF, debatable for GL or FX)
|
49
|
-
//
|
50
|
-
//
|
51
|
-
//
|
49
|
+
//Component initComponent(PApplet sketch);
|
50
|
+
//Frame initFrame(PApplet sketch, Color backgroundColor,
|
51
|
+
// void initFrame(PApplet sketch, int backgroundColor,
|
52
52
|
// int deviceIndex, boolean fullScreen, boolean spanDisplays);
|
53
53
|
/**
|
54
54
|
*
|
55
55
|
* @param sketch
|
56
56
|
*/
|
57
|
-
|
57
|
+
void initFrame(PApplet sketch);
|
58
58
|
|
59
59
|
/**
|
60
60
|
* Get the native window object associated with this drawing surface. For
|
@@ -66,7 +66,7 @@ public interface PSurface {
|
|
66
66
|
*
|
67
67
|
* @return
|
68
68
|
*/
|
69
|
-
|
69
|
+
Object getNative();
|
70
70
|
|
71
71
|
//
|
72
72
|
// Just call these on an AWT Frame object stored in PApplet.
|
@@ -77,73 +77,73 @@ public interface PSurface {
|
|
77
77
|
*
|
78
78
|
* @param title
|
79
79
|
*/
|
80
|
-
|
80
|
+
void setTitle(String title);
|
81
81
|
|
82
82
|
/**
|
83
83
|
* Show or hide the window.
|
84
84
|
*
|
85
85
|
* @param visible
|
86
86
|
*/
|
87
|
-
|
87
|
+
void setVisible(boolean visible);
|
88
88
|
|
89
89
|
/**
|
90
90
|
* Set true if we want to resize things (default is not resizable)
|
91
91
|
*
|
92
92
|
* @param resizable
|
93
93
|
*/
|
94
|
-
|
94
|
+
void setResizable(boolean resizable);
|
95
95
|
|
96
96
|
/**
|
97
97
|
* Dumb name, but inherited from Frame and no better ideas.
|
98
98
|
*
|
99
99
|
* @param always
|
100
100
|
*/
|
101
|
-
|
101
|
+
void setAlwaysOnTop(boolean always);
|
102
102
|
|
103
103
|
/**
|
104
104
|
*
|
105
105
|
* @param icon
|
106
106
|
*/
|
107
|
-
|
107
|
+
void setIcon(PImage icon);
|
108
108
|
|
109
109
|
//
|
110
|
-
//
|
110
|
+
// void placeWindow(int[] location);
|
111
111
|
/**
|
112
112
|
*
|
113
113
|
* @param location
|
114
114
|
* @param editorLocation
|
115
115
|
*/
|
116
|
-
|
116
|
+
void placeWindow(int[] location, int[] editorLocation);
|
117
117
|
|
118
|
-
//
|
118
|
+
//void placeFullScreen(boolean hideStop);
|
119
119
|
/**
|
120
120
|
*
|
121
121
|
* @param stopColor
|
122
122
|
*/
|
123
|
-
|
123
|
+
void placePresent(int stopColor);
|
124
124
|
|
125
125
|
// Sketch is running from the PDE, set up messaging back to the PDE
|
126
126
|
/**
|
127
127
|
*
|
128
128
|
*/
|
129
|
-
|
129
|
+
void setupExternalMessages();
|
130
130
|
|
131
131
|
//
|
132
132
|
// sets displayWidth/Height inside PApplet
|
133
|
-
//
|
133
|
+
//void checkDisplaySize();
|
134
134
|
/**
|
135
135
|
*
|
136
136
|
* @param x
|
137
137
|
* @param y
|
138
138
|
*/
|
139
|
-
|
139
|
+
void setLocation(int x, int y);
|
140
140
|
|
141
141
|
/**
|
142
142
|
*
|
143
143
|
* @param width
|
144
144
|
* @param height
|
145
145
|
*/
|
146
|
-
|
146
|
+
void setSize(int width, int height);
|
147
147
|
|
148
148
|
// /**
|
149
149
|
// * Called by {@link PApplet#createGraphics} to initialize the
|
@@ -154,32 +154,32 @@ public interface PSurface {
|
|
154
154
|
// * @param high
|
155
155
|
// */
|
156
156
|
// create pixel buffer (pulled out for offscreen graphics)
|
157
|
-
//
|
157
|
+
//void initImage(PGraphics gr, int wide, int high);
|
158
158
|
// create pixel buffer, called from allocate() to produce a compatible image for rendering efficiently
|
159
|
-
//
|
160
|
-
//
|
159
|
+
// void initImage(PGraphics gr);
|
160
|
+
//Component getComponent();
|
161
161
|
// /**
|
162
162
|
// * Sometimes smoothing must be set at the drawing surface level
|
163
163
|
// * not just inside the renderer itself.
|
164
164
|
// */
|
165
|
-
//
|
165
|
+
// void setSmooth(int level);
|
166
166
|
/**
|
167
167
|
*
|
168
168
|
* @param fps
|
169
169
|
*/
|
170
|
-
|
170
|
+
void setFrameRate(float fps);
|
171
171
|
|
172
172
|
// // called on the first frame so that the now-visible drawing surface can
|
173
173
|
// // receive key and mouse events
|
174
|
-
//
|
174
|
+
// void requestFocus();
|
175
175
|
// // finish rendering to the screen (called by PApplet)
|
176
|
-
//
|
176
|
+
// void blit();
|
177
177
|
//
|
178
178
|
/**
|
179
179
|
*
|
180
180
|
* @param kind
|
181
181
|
*/
|
182
|
-
|
182
|
+
void setCursor(int kind);
|
183
183
|
|
184
184
|
/**
|
185
185
|
*
|
@@ -187,46 +187,46 @@ public interface PSurface {
|
|
187
187
|
* @param hotspotX
|
188
188
|
* @param hotspotY
|
189
189
|
*/
|
190
|
-
|
190
|
+
void setCursor(PImage image, int hotspotX, int hotspotY);
|
191
191
|
|
192
192
|
/**
|
193
193
|
*
|
194
194
|
*/
|
195
|
-
|
195
|
+
void showCursor();
|
196
196
|
|
197
197
|
/**
|
198
198
|
*
|
199
199
|
*/
|
200
|
-
|
200
|
+
void hideCursor();
|
201
201
|
|
202
202
|
//
|
203
203
|
/**
|
204
204
|
* Start the animation thread
|
205
205
|
*/
|
206
|
-
|
206
|
+
void startThread();
|
207
207
|
|
208
208
|
/**
|
209
209
|
* On the next trip through the animation thread, things should go sleepy-bye.
|
210
210
|
* Does not pause the thread immediately because that needs to happen on the
|
211
211
|
* animation thread itself, so fires on the next trip through draw().
|
212
212
|
*/
|
213
|
-
|
213
|
+
void pauseThread();
|
214
214
|
|
215
215
|
/**
|
216
216
|
*
|
217
217
|
*/
|
218
|
-
|
218
|
+
void resumeThread();
|
219
219
|
|
220
220
|
/**
|
221
221
|
* Stop the animation thread (set it null)
|
222
222
|
*
|
223
223
|
* @return false if already stopped
|
224
224
|
*/
|
225
|
-
|
225
|
+
boolean stopThread();
|
226
226
|
|
227
227
|
/**
|
228
228
|
*
|
229
229
|
* @return
|
230
230
|
*/
|
231
|
-
|
231
|
+
boolean isStopped();
|
232
232
|
}
|
@@ -45,8 +45,8 @@ import processing.core.PConstants;
|
|
45
45
|
* represent groupings of values, we cannot simply use traditional
|
46
46
|
* addition/multiplication/etc. Instead, we'll need to do some "vector"
|
47
47
|
* math, which is made easy by the methods inside the <b>PVector</b>
|
48
|
-
* class
|
49
|
-
*
|
48
|
+
* class.
|
49
|
+
*
|
50
50
|
* The methods for this class are extensive. For a complete list, visit the
|
51
51
|
* <a
|
52
52
|
* href="http://processing.googlecode.com/svn/trunk/processing/build/javadoc/core/">developer's reference.</a>
|
@@ -1,12 +1,12 @@
|
|
1
1
|
package processing.data;
|
2
2
|
|
3
|
-
import java.io
|
3
|
+
import java.io.BufferedReader;
|
4
|
+
import java.io.PrintWriter;
|
4
5
|
import java.util.HashMap;
|
5
6
|
import java.util.Iterator;
|
6
7
|
|
7
8
|
import processing.core.PApplet;
|
8
9
|
|
9
|
-
|
10
10
|
/**
|
11
11
|
* A simple table class to use a String as a lookup for an float value.
|
12
12
|
*
|
@@ -16,37 +16,41 @@ import processing.core.PApplet;
|
|
16
16
|
*/
|
17
17
|
public class FloatDict {
|
18
18
|
|
19
|
-
/**
|
19
|
+
/**
|
20
|
+
* Number of elements in the table
|
21
|
+
*/
|
20
22
|
protected int count;
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
/**
|
25
|
+
*
|
26
|
+
*/
|
27
|
+
protected String[] keys;
|
26
28
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
/**
|
30
|
+
*
|
31
|
+
*/
|
32
|
+
protected float[] values;
|
31
33
|
|
32
|
-
/**
|
34
|
+
/**
|
35
|
+
* Internal implementation for faster lookups
|
36
|
+
*/
|
33
37
|
private HashMap<String, Integer> indices = new HashMap<>();
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
/**
|
40
|
+
*
|
41
|
+
*/
|
42
|
+
public FloatDict() {
|
39
43
|
count = 0;
|
40
44
|
keys = new String[10];
|
41
45
|
values = new float[10];
|
42
46
|
}
|
43
47
|
|
44
|
-
|
45
48
|
/**
|
46
49
|
* Create a new lookup with a specific size.This is more efficient than not
|
47
|
-
specifying a size. Use it when you know the rough size of the thing you're
|
50
|
+
* specifying a size. Use it when you know the rough size of the thing you're
|
51
|
+
* creating.
|
48
52
|
*
|
49
|
-
|
53
|
+
* @param length
|
50
54
|
* @nowebref
|
51
55
|
*/
|
52
56
|
public FloatDict(int length) {
|
@@ -55,12 +59,11 @@ public class FloatDict {
|
|
55
59
|
values = new float[length];
|
56
60
|
}
|
57
61
|
|
58
|
-
|
59
62
|
/**
|
60
|
-
* Read a set of entries from a Reader that has each key/value pair on
|
61
|
-
*
|
63
|
+
* Read a set of entries from a Reader that has each key/value pair on a
|
64
|
+
* single line, separated by a tab.
|
62
65
|
*
|
63
|
-
|
66
|
+
* @param reader
|
64
67
|
* @nowebref
|
65
68
|
*/
|
66
69
|
public FloatDict(BufferedReader reader) {
|
@@ -68,8 +71,8 @@ public class FloatDict {
|
|
68
71
|
keys = new String[lines.length];
|
69
72
|
values = new float[lines.length];
|
70
73
|
|
71
|
-
for (
|
72
|
-
String[] pieces = PApplet.split(
|
74
|
+
for (String line : lines) {
|
75
|
+
String[] pieces = PApplet.split(line, '\t');
|
73
76
|
if (pieces.length == 2) {
|
74
77
|
keys[count] = pieces[0];
|
75
78
|
values[count] = PApplet.parseFloat(pieces[1]);
|
@@ -79,10 +82,9 @@ public class FloatDict {
|
|
79
82
|
}
|
80
83
|
}
|
81
84
|
|
82
|
-
|
83
85
|
/**
|
84
|
-
|
85
|
-
|
86
|
+
* @param keys
|
87
|
+
* @param values
|
86
88
|
* @nowebref
|
87
89
|
*/
|
88
90
|
public FloatDict(String[] keys, float[] values) {
|
@@ -97,7 +99,6 @@ public class FloatDict {
|
|
97
99
|
}
|
98
100
|
}
|
99
101
|
|
100
|
-
|
101
102
|
/**
|
102
103
|
* Constructor to allow (more intuitive) inline initialization, e.g.:
|
103
104
|
* <pre>
|
@@ -106,7 +107,8 @@ public class FloatDict {
|
|
106
107
|
* { "key2", 2 }
|
107
108
|
* });
|
108
109
|
* </pre>
|
109
|
-
|
110
|
+
*
|
111
|
+
* @param pairs
|
110
112
|
*/
|
111
113
|
public FloatDict(Object[][] pairs) {
|
112
114
|
count = pairs.length;
|
@@ -119,23 +121,24 @@ public class FloatDict {
|
|
119
121
|
}
|
120
122
|
}
|
121
123
|
|
122
|
-
|
123
124
|
/**
|
124
|
-
|
125
|
-
* @webref floatdict:method
|
125
|
+
* @return @webref floatdict:method
|
126
126
|
* @brief Returns the number of key/value pairs
|
127
127
|
*/
|
128
128
|
public int size() {
|
129
129
|
return count;
|
130
130
|
}
|
131
131
|
|
132
|
-
|
133
132
|
/**
|
134
|
-
* Resize the internal data, this can only be used to shrink the list.Helpful
|
135
|
-
|
133
|
+
* Resize the internal data, this can only be used to shrink the list.Helpful
|
134
|
+
* for situations like sorting and then grabbing the top 50 entries.
|
135
|
+
*
|
136
|
+
* @param length
|
136
137
|
*/
|
137
138
|
public void resize(int length) {
|
138
|
-
if (length == count)
|
139
|
+
if (length == count) {
|
140
|
+
return;
|
141
|
+
}
|
139
142
|
|
140
143
|
if (length > count) {
|
141
144
|
throw new IllegalArgumentException("resize() can only be used to shrink the dictionary");
|
@@ -154,7 +157,6 @@ public class FloatDict {
|
|
154
157
|
resetIndices();
|
155
158
|
}
|
156
159
|
|
157
|
-
|
158
160
|
/**
|
159
161
|
* Remove all entries.
|
160
162
|
*
|
@@ -166,7 +168,6 @@ public class FloatDict {
|
|
166
168
|
indices = new HashMap<>();
|
167
169
|
}
|
168
170
|
|
169
|
-
|
170
171
|
private void resetIndices() {
|
171
172
|
indices = new HashMap<>(count);
|
172
173
|
for (int i = 0; i < count; i++) {
|
@@ -174,25 +175,21 @@ public class FloatDict {
|
|
174
175
|
}
|
175
176
|
}
|
176
177
|
|
177
|
-
|
178
178
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
179
|
+
/**
|
180
|
+
*
|
181
|
+
*/
|
182
|
+
public class Entry {
|
179
183
|
|
180
184
|
/**
|
181
185
|
*
|
182
186
|
*/
|
187
|
+
public String key;
|
183
188
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
*
|
189
|
-
*/
|
190
|
-
public String key;
|
191
|
-
|
192
|
-
/**
|
193
|
-
*
|
194
|
-
*/
|
195
|
-
public float value;
|
189
|
+
/**
|
190
|
+
*
|
191
|
+
*/
|
192
|
+
public float value;
|
196
193
|
|
197
194
|
Entry(String key, float value) {
|
198
195
|
this.key = key;
|
@@ -200,113 +197,101 @@ public class FloatDict {
|
|
200
197
|
}
|
201
198
|
}
|
202
199
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
return
|
209
|
-
|
210
|
-
public Iterator<Entry> iterator() {
|
211
|
-
return entryIterator();
|
212
|
-
}
|
213
|
-
};
|
200
|
+
/**
|
201
|
+
*
|
202
|
+
* @return
|
203
|
+
*/
|
204
|
+
public Iterable<Entry> entries() {
|
205
|
+
return () -> entryIterator();
|
214
206
|
}
|
215
207
|
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
208
|
+
/**
|
209
|
+
*
|
210
|
+
* @return
|
211
|
+
*/
|
212
|
+
public Iterator<Entry> entryIterator() {
|
221
213
|
return new Iterator<Entry>() {
|
222
214
|
int index = -1;
|
223
215
|
|
216
|
+
@Override
|
224
217
|
public void remove() {
|
225
218
|
removeIndex(index);
|
226
219
|
index--;
|
227
220
|
}
|
228
221
|
|
222
|
+
@Override
|
229
223
|
public Entry next() {
|
230
224
|
++index;
|
231
225
|
Entry e = new Entry(keys[index], values[index]);
|
232
226
|
return e;
|
233
227
|
}
|
234
228
|
|
229
|
+
@Override
|
235
230
|
public boolean hasNext() {
|
236
|
-
return index+1 < size();
|
231
|
+
return index + 1 < size();
|
237
232
|
}
|
238
233
|
};
|
239
234
|
}
|
240
235
|
|
241
|
-
|
242
236
|
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
*/
|
249
|
-
|
250
|
-
|
237
|
+
/**
|
238
|
+
*
|
239
|
+
* @param index
|
240
|
+
* @return
|
241
|
+
*/
|
251
242
|
public String key(int index) {
|
252
243
|
return keys[index];
|
253
244
|
}
|
254
245
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
246
|
+
/**
|
247
|
+
*
|
248
|
+
*/
|
249
|
+
protected void crop() {
|
259
250
|
if (count != keys.length) {
|
260
251
|
keys = PApplet.subset(keys, 0, count);
|
261
252
|
values = PApplet.subset(values, 0, count);
|
262
253
|
}
|
263
254
|
}
|
264
255
|
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
return
|
271
|
-
|
272
|
-
@Override
|
273
|
-
public Iterator<String> iterator() {
|
274
|
-
return keyIterator();
|
275
|
-
}
|
276
|
-
};
|
256
|
+
/**
|
257
|
+
*
|
258
|
+
* @return
|
259
|
+
*/
|
260
|
+
public Iterable<String> keys() {
|
261
|
+
return () -> keyIterator();
|
277
262
|
}
|
278
263
|
|
279
|
-
|
280
264
|
// Use this to iterate when you want to be able to remove elements along the way
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
*/
|
265
|
+
/**
|
266
|
+
*
|
267
|
+
* @return
|
268
|
+
*/
|
286
269
|
public Iterator<String> keyIterator() {
|
287
270
|
return new Iterator<String>() {
|
288
271
|
int index = -1;
|
289
272
|
|
273
|
+
@Override
|
290
274
|
public void remove() {
|
291
275
|
removeIndex(index);
|
292
276
|
index--;
|
293
277
|
}
|
294
278
|
|
279
|
+
@Override
|
295
280
|
public String next() {
|
296
281
|
return key(++index);
|
297
282
|
}
|
298
283
|
|
284
|
+
@Override
|
299
285
|
public boolean hasNext() {
|
300
|
-
return index+1 < size();
|
286
|
+
return index + 1 < size();
|
301
287
|
}
|
302
288
|
};
|
303
289
|
}
|
304
290
|
|
305
|
-
|
306
291
|
/**
|
307
292
|
* Return a copy of the internal keys array.This array can be modified.
|
308
293
|
*
|
309
|
-
|
294
|
+
* @return
|
310
295
|
* @webref floatdict:method
|
311
296
|
* @brief Return a copy of the internal keys array
|
312
297
|
*/
|
@@ -315,12 +300,12 @@ public class FloatDict {
|
|
315
300
|
return keyArray(null);
|
316
301
|
}
|
317
302
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
303
|
+
/**
|
304
|
+
*
|
305
|
+
* @param outgoing
|
306
|
+
* @return
|
307
|
+
*/
|
308
|
+
public String[] keyArray(String[] outgoing) {
|
324
309
|
if (outgoing == null || outgoing.length != count) {
|
325
310
|
outgoing = new String[count];
|
326
311
|
}
|
@@ -328,59 +313,53 @@ public class FloatDict {
|
|
328
313
|
return outgoing;
|
329
314
|
}
|
330
315
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
316
|
+
/**
|
317
|
+
*
|
318
|
+
* @param index
|
319
|
+
* @return
|
320
|
+
*/
|
321
|
+
public float value(int index) {
|
337
322
|
return values[index];
|
338
323
|
}
|
339
324
|
|
340
|
-
|
341
325
|
/**
|
342
|
-
|
343
|
-
* @webref floatdict:method
|
326
|
+
* @return @webref floatdict:method
|
344
327
|
* @brief Return the internal array being used to store the values
|
345
328
|
*/
|
346
329
|
public Iterable<Float> values() {
|
347
|
-
return
|
348
|
-
|
349
|
-
@Override
|
350
|
-
public Iterator<Float> iterator() {
|
351
|
-
return valueIterator();
|
352
|
-
}
|
353
|
-
};
|
330
|
+
return () -> valueIterator();
|
354
331
|
}
|
355
332
|
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
333
|
+
/**
|
334
|
+
*
|
335
|
+
* @return
|
336
|
+
*/
|
337
|
+
public Iterator<Float> valueIterator() {
|
361
338
|
return new Iterator<Float>() {
|
362
339
|
int index = -1;
|
363
340
|
|
341
|
+
@Override
|
364
342
|
public void remove() {
|
365
343
|
removeIndex(index);
|
366
344
|
index--;
|
367
345
|
}
|
368
346
|
|
347
|
+
@Override
|
369
348
|
public Float next() {
|
370
349
|
return value(++index);
|
371
350
|
}
|
372
351
|
|
352
|
+
@Override
|
373
353
|
public boolean hasNext() {
|
374
|
-
return index+1 < size();
|
354
|
+
return index + 1 < size();
|
375
355
|
}
|
376
356
|
};
|
377
357
|
}
|
378
358
|
|
379
|
-
|
380
359
|
/**
|
381
360
|
* Create a new array and copy each of the values into it.
|
382
361
|
*
|
383
|
-
|
362
|
+
* @return
|
384
363
|
* @webref floatdict:method
|
385
364
|
* @brief Create a new array and copy each of the values into it
|
386
365
|
*/
|
@@ -389,13 +368,13 @@ public class FloatDict {
|
|
389
368
|
return valueArray(null);
|
390
369
|
}
|
391
370
|
|
392
|
-
|
393
371
|
/**
|
394
372
|
* Fill an already-allocated array with the values (more efficient than
|
395
|
-
* creating a new array each time).If 'array' is null, or not the same
|
396
|
-
|
397
|
-
|
398
|
-
|
373
|
+
* creating a new array each time).If 'array' is null, or not the same size as
|
374
|
+
* the number of values, a new array will be allocated and returned.
|
375
|
+
*
|
376
|
+
* @param array
|
377
|
+
* @return
|
399
378
|
*/
|
400
379
|
public float[] valueArray(float[] array) {
|
401
380
|
if (array == null || array.length != size()) {
|
@@ -405,12 +384,11 @@ public class FloatDict {
|
|
405
384
|
return array;
|
406
385
|
}
|
407
386
|
|
408
|
-
|
409
387
|
/**
|
410
388
|
* Return a value for the specified key.
|
411
389
|
*
|
412
|
-
|
413
|
-
|
390
|
+
* @param key
|
391
|
+
* @return
|
414
392
|
* @webref floatdict:method
|
415
393
|
* @brief Return a value for the specified key
|
416
394
|
*/
|
@@ -422,13 +400,13 @@ public class FloatDict {
|
|
422
400
|
return values[index];
|
423
401
|
}
|
424
402
|
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
403
|
+
/**
|
404
|
+
*
|
405
|
+
* @param key
|
406
|
+
* @param alternate
|
407
|
+
* @return
|
408
|
+
*/
|
409
|
+
public float get(String key, float alternate) {
|
432
410
|
int index = index(key);
|
433
411
|
if (index == -1) {
|
434
412
|
return alternate;
|
@@ -436,10 +414,9 @@ public class FloatDict {
|
|
436
414
|
return values[index];
|
437
415
|
}
|
438
416
|
|
439
|
-
|
440
417
|
/**
|
441
|
-
|
442
|
-
|
418
|
+
* @param key
|
419
|
+
* @param amount
|
443
420
|
* @webref floatdict:method
|
444
421
|
* @brief Create a new key/value pair or change the value of one
|
445
422
|
*/
|
@@ -452,13 +429,13 @@ public class FloatDict {
|
|
452
429
|
}
|
453
430
|
}
|
454
431
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
432
|
+
/**
|
433
|
+
*
|
434
|
+
* @param index
|
435
|
+
* @param key
|
436
|
+
* @param value
|
437
|
+
*/
|
438
|
+
public void setIndex(int index, String key, float value) {
|
462
439
|
if (index < 0 || index >= count) {
|
463
440
|
throw new ArrayIndexOutOfBoundsException(index);
|
464
441
|
}
|
@@ -466,10 +443,9 @@ public class FloatDict {
|
|
466
443
|
values[index] = value;
|
467
444
|
}
|
468
445
|
|
469
|
-
|
470
446
|
/**
|
471
|
-
|
472
|
-
|
447
|
+
* @param key
|
448
|
+
* @return
|
473
449
|
* @webref floatdict:method
|
474
450
|
* @brief Check if a key is a part of the data structure
|
475
451
|
*/
|
@@ -477,10 +453,9 @@ public class FloatDict {
|
|
477
453
|
return index(key) != -1;
|
478
454
|
}
|
479
455
|
|
480
|
-
|
481
456
|
/**
|
482
|
-
|
483
|
-
|
457
|
+
* @param key
|
458
|
+
* @param amount
|
484
459
|
* @webref floatdict:method
|
485
460
|
* @brief Add to a value
|
486
461
|
*/
|
@@ -493,10 +468,9 @@ public class FloatDict {
|
|
493
468
|
}
|
494
469
|
}
|
495
470
|
|
496
|
-
|
497
471
|
/**
|
498
|
-
|
499
|
-
|
472
|
+
* @param key
|
473
|
+
* @param amount
|
500
474
|
* @webref floatdict:method
|
501
475
|
* @brief Subtract from a value
|
502
476
|
*/
|
@@ -504,10 +478,9 @@ public class FloatDict {
|
|
504
478
|
add(key, -amount);
|
505
479
|
}
|
506
480
|
|
507
|
-
|
508
481
|
/**
|
509
|
-
|
510
|
-
|
482
|
+
* @param key
|
483
|
+
* @param amount
|
511
484
|
* @webref floatdict:method
|
512
485
|
* @brief Multiply a value
|
513
486
|
*/
|
@@ -518,10 +491,9 @@ public class FloatDict {
|
|
518
491
|
}
|
519
492
|
}
|
520
493
|
|
521
|
-
|
522
494
|
/**
|
523
|
-
|
524
|
-
|
495
|
+
* @param key
|
496
|
+
* @param amount
|
525
497
|
* @webref floatdict:method
|
526
498
|
* @brief Divide a value
|
527
499
|
*/
|
@@ -532,25 +504,24 @@ public class FloatDict {
|
|
532
504
|
}
|
533
505
|
}
|
534
506
|
|
535
|
-
|
536
507
|
private void checkMinMax(String functionName) {
|
537
508
|
if (count == 0) {
|
538
|
-
String msg
|
539
|
-
String.format("Cannot use %s() on an empty %s.",
|
540
|
-
|
509
|
+
String msg
|
510
|
+
= String.format("Cannot use %s() on an empty %s.",
|
511
|
+
functionName, getClass().getSimpleName());
|
541
512
|
throw new RuntimeException(msg);
|
542
513
|
}
|
543
514
|
}
|
544
515
|
|
545
|
-
|
546
516
|
/**
|
547
|
-
|
548
|
-
* @webref floatlist:method
|
517
|
+
* @return @webref floatlist:method
|
549
518
|
* @brief Return the smallest value
|
550
519
|
*/
|
551
520
|
public int minIndex() {
|
552
521
|
//checkMinMax("minIndex");
|
553
|
-
if (count == 0)
|
522
|
+
if (count == 0) {
|
523
|
+
return -1;
|
524
|
+
}
|
554
525
|
|
555
526
|
// Will still return NaN if there are 1 or more entries, and they're all NaN
|
556
527
|
float m = Float.NaN;
|
@@ -562,7 +533,7 @@ public class FloatDict {
|
|
562
533
|
mi = i;
|
563
534
|
|
564
535
|
// calculate the rest
|
565
|
-
for (int j = i+1; j < count; j++) {
|
536
|
+
for (int j = i + 1; j < count; j++) {
|
566
537
|
float d = values[j];
|
567
538
|
if ((d == d) && (d < m)) {
|
568
539
|
m = values[j];
|
@@ -575,13 +546,11 @@ public class FloatDict {
|
|
575
546
|
return mi;
|
576
547
|
}
|
577
548
|
|
578
|
-
|
579
549
|
// return the key for the minimum value
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
*/
|
550
|
+
/**
|
551
|
+
*
|
552
|
+
* @return
|
553
|
+
*/
|
585
554
|
public String minKey() {
|
586
555
|
checkMinMax("minKey");
|
587
556
|
int index = minIndex();
|
@@ -591,13 +560,11 @@ public class FloatDict {
|
|
591
560
|
return keys[index];
|
592
561
|
}
|
593
562
|
|
594
|
-
|
595
563
|
// return the minimum value, or throw an error if there are no values
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
*/
|
564
|
+
/**
|
565
|
+
*
|
566
|
+
* @return
|
567
|
+
*/
|
601
568
|
public float minValue() {
|
602
569
|
checkMinMax("minValue");
|
603
570
|
int index = minIndex();
|
@@ -607,10 +574,8 @@ public class FloatDict {
|
|
607
574
|
return values[index];
|
608
575
|
}
|
609
576
|
|
610
|
-
|
611
577
|
/**
|
612
|
-
|
613
|
-
* @webref floatlist:method
|
578
|
+
* @return @webref floatlist:method
|
614
579
|
* @brief Return the largest value
|
615
580
|
*/
|
616
581
|
// The index of the entry that has the max value. Reference above is incorrect.
|
@@ -629,7 +594,7 @@ public class FloatDict {
|
|
629
594
|
mi = i;
|
630
595
|
|
631
596
|
// calculate the rest
|
632
|
-
for (int j = i+1; j < count; j++) {
|
597
|
+
for (int j = i + 1; j < count; j++) {
|
633
598
|
float d = values[j];
|
634
599
|
if (!Float.isNaN(d) && (d > m)) {
|
635
600
|
m = values[j];
|
@@ -642,9 +607,11 @@ public class FloatDict {
|
|
642
607
|
return mi;
|
643
608
|
}
|
644
609
|
|
645
|
-
|
646
|
-
|
647
|
-
|
610
|
+
/**
|
611
|
+
* The key for a max value; null if empty or everything is NaN (no max).
|
612
|
+
*
|
613
|
+
* @return
|
614
|
+
*/
|
648
615
|
public String maxKey() {
|
649
616
|
//checkMinMax("maxKey");
|
650
617
|
int index = maxIndex();
|
@@ -654,9 +621,11 @@ public class FloatDict {
|
|
654
621
|
return keys[index];
|
655
622
|
}
|
656
623
|
|
657
|
-
|
658
|
-
|
659
|
-
|
624
|
+
/**
|
625
|
+
* * The max value.(Or NaN if no entries or they're all NaN.)
|
626
|
+
*
|
627
|
+
* @return
|
628
|
+
*/
|
660
629
|
public float maxValue() {
|
661
630
|
//checkMinMax("maxValue");
|
662
631
|
int index = maxIndex();
|
@@ -666,11 +635,11 @@ public class FloatDict {
|
|
666
635
|
return values[index];
|
667
636
|
}
|
668
637
|
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
638
|
+
/**
|
639
|
+
*
|
640
|
+
* @return
|
641
|
+
*/
|
642
|
+
public float sum() {
|
674
643
|
double amount = sumDouble();
|
675
644
|
if (amount > Float.MAX_VALUE) {
|
676
645
|
throw new RuntimeException("sum() exceeds " + Float.MAX_VALUE + ", use sumDouble()");
|
@@ -681,11 +650,11 @@ public class FloatDict {
|
|
681
650
|
return (float) amount;
|
682
651
|
}
|
683
652
|
|
684
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
653
|
+
/**
|
654
|
+
*
|
655
|
+
* @return
|
656
|
+
*/
|
657
|
+
public double sumDouble() {
|
689
658
|
double sum = 0;
|
690
659
|
for (int i = 0; i < count; i++) {
|
691
660
|
sum += values[i];
|
@@ -693,36 +662,35 @@ public class FloatDict {
|
|
693
662
|
return sum;
|
694
663
|
}
|
695
664
|
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
665
|
+
/**
|
666
|
+
*
|
667
|
+
* @param what
|
668
|
+
* @return
|
669
|
+
*/
|
670
|
+
public int index(String what) {
|
702
671
|
Integer found = indices.get(what);
|
703
|
-
return (found == null) ? -1 : found
|
672
|
+
return (found == null) ? -1 : found;
|
704
673
|
}
|
705
674
|
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
675
|
+
/**
|
676
|
+
*
|
677
|
+
* @param what
|
678
|
+
* @param much
|
679
|
+
*/
|
680
|
+
protected void create(String what, float much) {
|
712
681
|
if (count == keys.length) {
|
713
682
|
keys = PApplet.expand(keys);
|
714
683
|
values = PApplet.expand(values);
|
715
684
|
}
|
716
|
-
indices.put(what,
|
685
|
+
indices.put(what, count);
|
717
686
|
keys[count] = what;
|
718
687
|
values[count] = much;
|
719
688
|
count++;
|
720
689
|
}
|
721
690
|
|
722
|
-
|
723
691
|
/**
|
724
|
-
|
725
|
-
|
692
|
+
* @param key
|
693
|
+
* @return
|
726
694
|
* @webref floatdict:method
|
727
695
|
* @brief Remove a key/value pair
|
728
696
|
*/
|
@@ -734,21 +702,21 @@ public class FloatDict {
|
|
734
702
|
return index;
|
735
703
|
}
|
736
704
|
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
|
741
|
-
|
742
|
-
|
705
|
+
/**
|
706
|
+
*
|
707
|
+
* @param index
|
708
|
+
* @return
|
709
|
+
*/
|
710
|
+
public String removeIndex(int index) {
|
743
711
|
if (index < 0 || index >= count) {
|
744
712
|
throw new ArrayIndexOutOfBoundsException(index);
|
745
713
|
}
|
746
714
|
String key = keys[index];
|
747
715
|
//System.out.println("index is " + which + " and " + keys[which]);
|
748
716
|
indices.remove(keys[index]);
|
749
|
-
for (int i = index; i < count-1; i++) {
|
750
|
-
keys[i] = keys[i+1];
|
751
|
-
values[i] = values[i+1];
|
717
|
+
for (int i = index; i < count - 1; i++) {
|
718
|
+
keys[i] = keys[i + 1];
|
719
|
+
values[i] = values[i + 1];
|
752
720
|
indices.put(keys[i], i);
|
753
721
|
}
|
754
722
|
count--;
|
@@ -757,12 +725,12 @@ public class FloatDict {
|
|
757
725
|
return key;
|
758
726
|
}
|
759
727
|
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
|
728
|
+
/**
|
729
|
+
*
|
730
|
+
* @param a
|
731
|
+
* @param b
|
732
|
+
*/
|
733
|
+
public void swap(int a, int b) {
|
766
734
|
String tkey = keys[a];
|
767
735
|
float tvalue = values[a];
|
768
736
|
keys[a] = keys[b];
|
@@ -774,7 +742,6 @@ public class FloatDict {
|
|
774
742
|
// indices.put(keys[b], Integer.valueOf(b));
|
775
743
|
}
|
776
744
|
|
777
|
-
|
778
745
|
/**
|
779
746
|
* Sort the keys alphabetically (ignoring case). Uses the value as a
|
780
747
|
* tie-breaker (only really possible with a key that has a case change).
|
@@ -786,7 +753,6 @@ public class FloatDict {
|
|
786
753
|
sortImpl(true, false, true);
|
787
754
|
}
|
788
755
|
|
789
|
-
|
790
756
|
/**
|
791
757
|
* @webref floatdict:method
|
792
758
|
* @brief Sort the keys alphabetically in reverse
|
@@ -795,7 +761,6 @@ public class FloatDict {
|
|
795
761
|
sortImpl(true, true, true);
|
796
762
|
}
|
797
763
|
|
798
|
-
|
799
764
|
/**
|
800
765
|
* Sort by values in descending order (largest value will be at [0]).
|
801
766
|
*
|
@@ -806,17 +771,16 @@ public class FloatDict {
|
|
806
771
|
sortValues(true);
|
807
772
|
}
|
808
773
|
|
809
|
-
|
810
774
|
/**
|
811
|
-
* Set true to ensure that the order returned is identical. Slightly
|
812
|
-
*
|
775
|
+
* Set true to ensure that the order returned is identical. Slightly slower
|
776
|
+
* because the tie-breaker for identical values compares the keys.
|
777
|
+
*
|
813
778
|
* @param stable
|
814
779
|
*/
|
815
780
|
public void sortValues(boolean stable) {
|
816
781
|
sortImpl(false, false, stable);
|
817
782
|
}
|
818
783
|
|
819
|
-
|
820
784
|
/**
|
821
785
|
* @webref floatdict:method
|
822
786
|
* @brief Sort by values in descending order
|
@@ -825,22 +789,22 @@ public class FloatDict {
|
|
825
789
|
sortValuesReverse(true);
|
826
790
|
}
|
827
791
|
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
792
|
+
/**
|
793
|
+
*
|
794
|
+
* @param stable
|
795
|
+
*/
|
796
|
+
public void sortValuesReverse(boolean stable) {
|
833
797
|
sortImpl(false, true, stable);
|
834
798
|
}
|
835
799
|
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
800
|
+
/**
|
801
|
+
*
|
802
|
+
* @param useKeys
|
803
|
+
* @param reverse
|
804
|
+
* @param stable
|
805
|
+
*/
|
806
|
+
protected void sortImpl(final boolean useKeys, final boolean reverse,
|
807
|
+
final boolean stable) {
|
844
808
|
Sort s = new Sort() {
|
845
809
|
@Override
|
846
810
|
public int size() {
|
@@ -896,11 +860,12 @@ public class FloatDict {
|
|
896
860
|
resetIndices();
|
897
861
|
}
|
898
862
|
|
899
|
-
|
900
863
|
/**
|
901
864
|
* Sum all of the values in this dictionary, then return a new FloatDict of
|
902
865
|
* each key, divided by the total sum. The total for all values will be ~1.0.
|
903
|
-
*
|
866
|
+
*
|
867
|
+
* @return a FloatDict with the original keys, mapped to their pct of the
|
868
|
+
* total
|
904
869
|
*/
|
905
870
|
public FloatDict getPercent() {
|
906
871
|
double sum = sum();
|
@@ -912,9 +877,11 @@ public class FloatDict {
|
|
912
877
|
return outgoing;
|
913
878
|
}
|
914
879
|
|
915
|
-
|
916
|
-
|
917
|
-
|
880
|
+
/**
|
881
|
+
* Returns a duplicate copy of this object.
|
882
|
+
*
|
883
|
+
* @return
|
884
|
+
*/
|
918
885
|
public FloatDict copy() {
|
919
886
|
FloatDict outgoing = new FloatDict(count);
|
920
887
|
System.arraycopy(keys, 0, outgoing.keys, 0, count);
|
@@ -926,18 +893,18 @@ public class FloatDict {
|
|
926
893
|
return outgoing;
|
927
894
|
}
|
928
895
|
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
896
|
+
/**
|
897
|
+
*
|
898
|
+
*/
|
899
|
+
public void print() {
|
933
900
|
for (int i = 0; i < size(); i++) {
|
934
901
|
System.out.println(keys[i] + " = " + values[i]);
|
935
902
|
}
|
936
903
|
}
|
937
904
|
|
938
|
-
|
939
905
|
/**
|
940
906
|
* Write tab-delimited entries out to
|
907
|
+
*
|
941
908
|
* @param writer
|
942
909
|
*/
|
943
910
|
public void write(PrintWriter writer) {
|
@@ -947,24 +914,24 @@ public class FloatDict {
|
|
947
914
|
writer.flush();
|
948
915
|
}
|
949
916
|
|
950
|
-
|
951
917
|
/**
|
952
918
|
* Return this dictionary as a String in JSON format.
|
953
|
-
|
919
|
+
*
|
920
|
+
* @return
|
954
921
|
*/
|
955
922
|
public String toJSON() {
|
956
923
|
StringList items = new StringList();
|
957
924
|
for (int i = 0; i < count; i++) {
|
958
|
-
items.append(JSONObject.quote(keys[i])+ ": " + values[i]);
|
925
|
+
items.append(JSONObject.quote(keys[i]) + ": " + values[i]);
|
959
926
|
}
|
960
927
|
return "{ " + items.join(", ") + " }";
|
961
928
|
}
|
962
929
|
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
|
930
|
+
/**
|
931
|
+
*
|
932
|
+
* @return
|
933
|
+
*/
|
934
|
+
@Override
|
968
935
|
public String toString() {
|
969
936
|
return getClass().getSimpleName() + " size=" + size() + " " + toJSON();
|
970
937
|
}
|