author | rougeronj |
Thu, 16 Apr 2015 12:15:33 +0200 | |
changeset 153 | 60bd2b36b9dc |
parent 131 | 0bb70072a56f |
permissions | -rw-r--r-- |
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
1 |
/** |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
2 |
* js/annotsRoll.js |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
3 |
* |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
4 |
* annotsRoll basic component |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
5 |
* |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
6 |
*/ |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
7 |
|
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
8 |
'use strict'; |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
9 |
|
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
10 |
var PIXI = require('pixi'); |
98 | 11 |
var _ = require('lodash'); |
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
12 |
|
98 | 13 |
var DEFAULT_ANNOT_COLOR = '#bababa'; |
14 |
||
15 |
var defaultAnnotStyles = { |
|
106
9b20ddf1fc70
Add WordWrap to annots text style to crates multilines if the text is to large
rougeronj
parents:
105
diff
changeset
|
16 |
'label': { font: '16pt Arial Bold', fill: '#65A954', wordWrap: true}, |
9b20ddf1fc70
Add WordWrap to annots text style to crates multilines if the text is to large
rougeronj
parents:
105
diff
changeset
|
17 |
'text' : { font: '12pt Arial Regular', fill: '#444444', wordWrap: true}, |
105
25ac8802c189
Improve interface + Add horizontal pianoroll to annotsvizview
rougeronj
parents:
103
diff
changeset
|
18 |
'user' : { font: '14pt Arial regular', fill: '#666666' }, |
98 | 19 |
}; |
20 |
||
21 |
var defaultOptions = { |
|
22 |
externalRefresh: false, |
|
23 |
defaultColor: DEFAULT_ANNOT_COLOR, |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
24 |
annotStyles: defaultAnnotStyles, |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
25 |
ignoreAnnots:false |
98 | 26 |
}; |
27 |
||
28 |
function AnnotsRoll(options) { |
|
29 |
||
30 |
//parentContainer, xInit, yInit, width, height, widthRoll, pixelsPerSecond, annotColors |
|
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
31 |
var _this = this; |
98 | 32 |
var opts = _(options).defaults(defaultOptions).value(); |
33 |
||
34 |
||
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
35 |
this.container = new PIXI.DisplayObjectContainer(); |
98 | 36 |
this.container.x = opts.xInit; |
37 |
this.container.y = opts.yInit; |
|
38 |
this.container.width = opts.width; |
|
39 |
||
40 |
this.height = opts.height; |
|
41 |
this.width = opts.width; |
|
42 |
this.widthRoll = opts.widthRoll; |
|
43 |
this.pixelsPerSecond = opts.pixelsPerSecond; |
|
44 |
this.annotColors = opts.annotColors; |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
45 |
this.startTs = opts.startTs || Date.now(); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
46 |
this.ignoreAnnots = opts.ignoreAnnots; |
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
47 |
|
98 | 48 |
var yInit = opts.yInit; |
49 |
var annotStyles = _(opts.annotStyles).defaults(defaultAnnotStyles).value(); |
|
120 | 50 |
var marginX = 15; |
106
9b20ddf1fc70
Add WordWrap to annots text style to crates multilines if the text is to large
rougeronj
parents:
105
diff
changeset
|
51 |
for(var style in annotStyles) { |
9b20ddf1fc70
Add WordWrap to annots text style to crates multilines if the text is to large
rougeronj
parents:
105
diff
changeset
|
52 |
if (annotStyles[style].wordWrap === true){ |
131 | 53 |
annotStyles[style].wordWrapWidth = this.widthRoll - marginX; |
106
9b20ddf1fc70
Add WordWrap to annots text style to crates multilines if the text is to large
rougeronj
parents:
105
diff
changeset
|
54 |
} |
9b20ddf1fc70
Add WordWrap to annots text style to crates multilines if the text is to large
rougeronj
parents:
105
diff
changeset
|
55 |
} |
98 | 56 |
var started = false; |
57 |
var ws = opts.ws; |
|
58 |
var externalRefresh = opts.externalRefresh; |
|
100 | 59 |
var stageView = opts.stageView; |
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
60 |
var waitInterval; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
61 |
var wait = 0; |
131 | 62 |
|
100 | 63 |
stageView.registerComponent(this); |
98 | 64 |
|
65 |
var isHidden = function(child) { |
|
66 |
// TODO: the origin point is an approximation. Should refine this |
|
67 |
var globalPos = child.toGlobal(new PIXI.Point(0,0)); |
|
68 |
return ((globalPos.x + child.width) < 0) || ((globalPos.y + child.height) < 0) ; |
|
69 |
}; |
|
70 |
||
71 |
this.addAnnots = function(data) { |
|
72 |
||
73 |
//var title = data.content.category.label; |
|
74 |
//var user = data.content.user; |
|
75 |
//Test cat and color |
|
76 |
//var colorAnnot = 0x65A954; |
|
77 |
var category = data.content.category.label, |
|
78 |
text = data.content.text, |
|
79 |
user = data.content.user, |
|
80 |
ts = Date.parse(data.ts), |
|
122
3b11017a76a4
Merge with e6605fecb175a2d880aa3448085f48bfcaffd29b + minor update about color pic in annostroll
rougeronj
parents:
120
diff
changeset
|
81 |
color = data.content.color || this.getColor(ts, data.content.category.code); |
98 | 82 |
|
83 |
this.addAnnot(category, text, user, color, ts); |
|
84 |
}; |
|
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
85 |
|
98 | 86 |
this.getColor = function(ts, code) { |
87 |
var colorsDef; |
|
88 |
_(this.annotColors).eachRight(function(cdef) { |
|
89 |
if(cdef.ts < ts) { |
|
90 |
colorsDef = cdef.colors; |
|
91 |
return false; |
|
92 |
} |
|
93 |
}); |
|
94 |
var resColor; |
|
95 |
if(colorsDef) { |
|
96 |
resColor = colorsDef[code]; |
|
97 |
} |
|
98 |
if(!resColor) { |
|
123
d8ef840eaf68
get the correct json category depending on the timestamp
rougeronj
parents:
122
diff
changeset
|
99 |
resColor = colorsDef.defaultColor || DEFAULT_ANNOT_COLOR; |
98 | 100 |
} |
101 |
return resColor; |
|
131 | 102 |
}; |
98 | 103 |
|
122
3b11017a76a4
Merge with e6605fecb175a2d880aa3448085f48bfcaffd29b + minor update about color pic in annostroll
rougeronj
parents:
120
diff
changeset
|
104 |
this.addAnnot = function(category, text, user, color, ts){ |
98 | 105 |
|
106 |
var x = 0; |
|
107 |
var y = (ts-this.startTs) * this.pixelsPerSecond / 1000 + yInit; |
|
108 |
||
109 |
var colorHex = parseInt(color.replace(/^#/, ''), 16); |
|
110 |
||
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
111 |
if (wait === 0){ |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
112 |
var graphics = new PIXI.Graphics() |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
113 |
.beginFill(colorHex) |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
114 |
.drawRect(x, y, 10, 3) |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
115 |
.endFill(); |
131 | 116 |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
117 |
this.container.addChild(graphics); |
131 | 118 |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
119 |
var textHeight = 0; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
120 |
var catLabel = new PIXI.Text( |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
121 |
category, |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
122 |
_(annotStyles.label).extend({fill: color}).value() |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
123 |
); |
120 | 124 |
catLabel.x = x + marginX; |
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
125 |
catLabel.y = y - 23; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
126 |
this.container.addChild(catLabel); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
127 |
textHeight += (catLabel.height - 23 + 2); |
131 | 128 |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
129 |
if(text) { |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
130 |
var catText = new PIXI.Text(text, annotStyles.text); |
120 | 131 |
catText.x = x + marginX; |
117
c0034b35c44e
merge + gulp + correction of superposition category-text
rougeronj
parents:
112
diff
changeset
|
132 |
catText.y = y + textHeight; |
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
133 |
this.container.addChild(catText); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
134 |
textHeight += (catText.height + 2); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
135 |
} |
131 | 136 |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
137 |
var catUser = new PIXI.Text(user, annotStyles.user); |
120 | 138 |
catUser.x = x + marginX; |
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
139 |
catUser.y = y + textHeight; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
140 |
this.container.addChild(catUser); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
141 |
textHeight += (catUser.height + 8); |
131 | 142 |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
143 |
if (this.ignoreAnnots === true){ |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
144 |
wait = textHeight / this.pixelsPerSecond; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
145 |
waitInterval = setInterval(function() {_this.refreshWait();}, 1000); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
146 |
} |
98 | 147 |
} |
148 |
||
149 |
this.addAnnotLine(colorHex, y); |
|
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
150 |
}; |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
151 |
|
98 | 152 |
this.addAnnotLine = function(color, y) { |
153 |
var x = this.widthRoll; |
|
154 |
||
155 |
||
156 |
var graphics = new PIXI.Graphics() |
|
157 |
.beginFill(color) |
|
158 |
.drawRect(x, y, this.width - x, 3) |
|
159 |
.endFill(); |
|
160 |
||
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
161 |
this.container.addChild(graphics); |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
162 |
}; |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
163 |
|
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
164 |
this.moveTo = function(diffTime){ |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
165 |
this.container.y = Math.floor(diffTime*this.pixelsPerSecond); |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
166 |
}; |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
167 |
|
98 | 168 |
this.move = this.refresh = function() { |
169 |
var diff = (this.startTs - Date.now())/1000; |
|
170 |
this.moveTo(diff); |
|
171 |
}; |
|
131 | 172 |
|
111
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
173 |
this.refreshWait = function(){ |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
174 |
wait -= 1; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
175 |
if (wait < 0){ |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
176 |
wait = 0; |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
177 |
clearInterval(waitInterval); |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
178 |
} |
a7b72620d227
Add variable "wait". When this variable set, the annotsroll wait ignore some annotations, and wait before printing an otherone so there is no superposition. Can be passed as an options
rougeronj
parents:
106
diff
changeset
|
179 |
}; |
98 | 180 |
|
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
181 |
this.removePassedObjets = function(){ |
98 | 182 |
var childrenToRemove = []; |
183 |
_(_this.container.children).forEach(function(child) { |
|
184 |
return typeof(child) === 'undefined' || |
|
185 |
(isHidden(child) && childrenToRemove.push(child)); |
|
186 |
}); |
|
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
187 |
childrenToRemove.forEach(function(child) { |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
188 |
_this.container.removeChild(child); |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
189 |
}); |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
190 |
}; |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
191 |
|
98 | 192 |
this.init = function() { |
193 |
||
194 |
ws.message(function(data) { |
|
195 |
_this.addAnnots(data); |
|
196 |
}); |
|
197 |
||
198 |
}; |
|
131 | 199 |
|
98 | 200 |
|
201 |
this.start = function() { |
|
202 |
if(!started) { |
|
203 |
this.startTs = Date.now(); |
|
204 |
started = true; |
|
205 |
} |
|
206 |
this.cleanInterval = setInterval(function () { _this.removePassedObjets(); }, 1000 * this.height / this.pixelsPerSecond ); |
|
207 |
if(!externalRefresh) { |
|
208 |
this.refreshInterval = setInterval(function() {_this.move();}, 1000/this.framerate); |
|
209 |
} |
|
210 |
}; |
|
211 |
||
212 |
this.stop = function() { |
|
213 |
clearInterval(this.cleanInterval); |
|
214 |
if(!externalRefresh) { |
|
215 |
clearInterval(this.refreshInterval); |
|
216 |
} |
|
217 |
}; |
|
89
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
218 |
|
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
219 |
} |
b4bd49f01837
add annotsRoll class and create it in main. Adapt main and pianoroll to allow horizontal or vertical view
rougeronj
parents:
diff
changeset
|
220 |
|
98 | 221 |
module.exports = { |
222 |
AnnotsRoll: AnnotsRoll, |
|
223 |
}; |