Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
proview
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Esteban Blanc
proview
Commits
50f2898b
Commit
50f2898b
authored
Nov 26, 2020
by
Claes
Committed by
Esteban Blanc
Dec 23, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Trends, DsTrend, DsTrendCurve and SevHist for javascript
parent
12afe116
Changes
14
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
3531 additions
and
461 deletions
+3531
-461
java/exe/jpwr_rt_gdh/src/jpwr_rt_gdh.c
java/exe/jpwr_rt_gdh/src/jpwr_rt_gdh.c
+392
-1
java/exe/jpwr_rt_gdh/src/jpwr_rt_gdh.h
java/exe/jpwr_rt_gdh/src/jpwr_rt_gdh.h
+24
-0
java/jpwr/rt/src/Gdh.java
java/jpwr/rt/src/Gdh.java
+15
-0
java/jpwr/rt/src/GdhWebSocketServer.java
java/jpwr/rt/src/GdhWebSocketServer.java
+674
-2
java/jpwr/rt/src/GdhrGetDsTrend.java
java/jpwr/rt/src/GdhrGetDsTrend.java
+65
-0
java/jpwr/rt/src/GdhrSevItemData.java
java/jpwr/rt/src/GdhrSevItemData.java
+64
-0
java/jpwr/rt/src/GdhrSevItemInfo.java
java/jpwr/rt/src/GdhrSevItemInfo.java
+62
-0
java/jpwr/rt/src/makefile
java/jpwr/rt/src/makefile
+3
-0
java/jsw/cmn/src/gdh.jsi
java/jsw/cmn/src/gdh.jsi
+358
-1
java/jsw/cmn/src/glow.jsi
java/jsw/cmn/src/glow.jsi
+114
-9
java/jsw/ge/src/ge.js
java/jsw/ge/src/ge.js
+1743
-446
sev/lib/sev/src/sev_dbms.cpp
sev/lib/sev/src/sev_dbms.cpp
+8
-1
src/lib/rt/src/rt_cbuf.c
src/lib/rt/src/rt_cbuf.c
+8
-1
wb/exp/wb/src/pwr_wb_palette.cnf
wb/exp/wb/src/pwr_wb_palette.cnf
+1
-0
No files found.
java/exe/jpwr_rt_gdh/src/jpwr_rt_gdh.c
View file @
50f2898b
This diff is collapsed.
Click to expand it.
java/exe/jpwr_rt_gdh/src/jpwr_rt_gdh.h
View file @
50f2898b
...
...
@@ -407,6 +407,30 @@ JNIEXPORT jint JNICALL Java_jpwr_rt_Gdh_getCircBuffInfo
JNIEXPORT
jint
JNICALL
Java_jpwr_rt_Gdh_updateCircBuffInfo
(
JNIEnv
*
,
jobject
,
jobject
,
jint
);
/*
* Class: jpwr_rt_Gdh
* Method: getDsTrend
* Signature: (Ljava/lang/String;III)Ljpwr/rt/GdhrGetDsTrend;
*/
JNIEXPORT
jobject
JNICALL
Java_jpwr_rt_Gdh_getDsTrend
(
JNIEnv
*
,
jobject
,
jstring
,
jint
,
jint
,
jint
);
/*
* Class: jpwr_rt_Gdh
* Method: getSevItemInfo
* Signature: (Ljava/lang/String;)Ljpwr/rt/GdhrSevItemInfo;
*/
JNIEXPORT
jobject
JNICALL
Java_jpwr_rt_Gdh_getSevItemInfo
(
JNIEnv
*
,
jobject
,
jstring
);
/*
* Class: jpwr_rt_Gdh
* Method: getSevItemData
* Signature: (Ljava/lang/String;Ljpwr/rt/PwrtObjid;Ljava/lang/String;FI)Ljpwr/rt/GdhrSevItemData;
*/
JNIEXPORT
jobject
JNICALL
Java_jpwr_rt_Gdh_getSevItemData
(
JNIEnv
*
,
jobject
,
jstring
,
jobject
,
jstring
,
jfloat
,
jint
);
#ifdef __cplusplus
}
#endif
...
...
java/jpwr/rt/src/Gdh.java
View file @
50f2898b
...
...
@@ -700,6 +700,21 @@ public class Gdh {
*/
public
native
int
updateCircBuffInfo
(
CircBuffInfo
[]
info
,
int
info_size
);
// public native GdhrGetXttObj[] getAllXttChildrenNative(PwrtObjid objid);
/**
Get data from a DsTrend.
*/
public
native
GdhrGetDsTrend
getDsTrend
(
String
jstrend_object
,
int
last_next_idx
,
int
last_buffer
,
int
max_size
);
/**
Get info of a sevhist object.
*/
public
native
GdhrSevItemInfo
getSevItemInfo
(
String
jsevhist_object
);
/**
Get data from a sevhist item.
*/
public
native
GdhrSevItemData
getSevItemData
(
String
jserver
,
PwrtObjid
oid
,
String
jattribute
,
float
timerange
,
int
max_size
);
}
...
...
java/jpwr/rt/src/GdhWebSocketServer.java
View file @
50f2898b
This diff is collapsed.
Click to expand it.
java/jpwr/rt/src/GdhrGetDsTrend.java
0 → 100644
View file @
50f2898b
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2020 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
package
jpwr.rt
;
import
java.io.Serializable
;
/**
Return class for functions returning cicular buffer information.
Contains a return status and circular buffer information.
*/
public
class
GdhrGetDsTrend
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
2632525127459438144L
;
public
int
sts
;
public
int
last_next_idx
;
public
int
last_buffer
;
public
int
size
;
public
float
[]
data
;
public
GdhrGetDsTrend
(
float
[]
data
,
int
size
,
int
last_next_idx
,
int
last_buffer
,
int
sts
)
{
this
.
data
=
data
;
this
.
size
=
size
;
this
.
last_next_idx
=
last_next_idx
;
this
.
last_buffer
=
last_buffer
;
this
.
sts
=
sts
;
}
public
boolean
evenSts
()
{
return
(
sts
%
2
==
0
);}
public
boolean
oddSts
()
{
return
(
sts
%
2
==
1
);}
public
int
getSts
()
{
return
sts
;}
}
java/jpwr/rt/src/GdhrSevItemData.java
0 → 100644
View file @
50f2898b
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2020 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
package
jpwr.rt
;
import
java.io.Serializable
;
/**
Return class for functions returning cicular buffer information.
Contains a return status and circular buffer information.
*/
public
class
GdhrSevItemData
implements
Serializable
{
private
static
final
long
serialVersionUID
=
-
650888721059659030L
;
public
int
size
;
public
float
[]
tbuf
;
public
Object
vbuf
;
public
int
vtype
;
public
int
sts
;
public
GdhrSevItemData
(
int
size
,
float
[]
tbuf
,
Object
vbuf
,
int
vtype
,
int
sts
)
{
this
.
size
=
size
;
this
.
tbuf
=
tbuf
;
this
.
vbuf
=
vbuf
;
this
.
vtype
=
vtype
;
this
.
sts
=
sts
;
}
public
boolean
evenSts
()
{
return
(
sts
%
2
==
0
);}
public
boolean
oddSts
()
{
return
(
sts
%
2
==
1
);}
public
int
getSts
()
{
return
sts
;}
}
java/jpwr/rt/src/GdhrSevItemInfo.java
0 → 100644
View file @
50f2898b
/*
* ProviewR Open Source Process Control.
* Copyright (C) 2005-2020 SSAB EMEA AB.
*
* This file is part of ProviewR.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ProviewR. If not, see <http://www.gnu.org/licenses/>
*
* Linking ProviewR statically or dynamically with other modules is
* making a combined work based on ProviewR. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
*
* In addition, as a special exception, the copyright holders of
* ProviewR give you permission to, from the build function in the
* ProviewR Configurator, combine ProviewR with modules generated by the
* ProviewR PLC Editor to a PLC program, regardless of the license
* terms of these modules. You may copy and distribute the resulting
* combined work under the terms of your choice, provided that every
* copy of the combined work is accompanied by a complete copy of
* the source code of ProviewR (the version used to produce the
* combined work), being distributed under the terms of the GNU
* General Public License plus this exception.
*/
package
jpwr.rt
;
import
java.io.Serializable
;
/**
Return class for functions returning cicular buffer information.
Contains a return status and circular buffer information.
*/
public
class
GdhrSevItemInfo
implements
Serializable
{
private
static
final
long
serialVersionUID
=
2932793763480084882L
;
public
PwrtObjid
oid
;
public
String
attr
;
public
String
server
;
public
int
sts
;
public
GdhrSevItemInfo
(
PwrtObjid
oid
,
String
attr
,
String
server
,
int
sts
)
{
this
.
oid
=
oid
;
this
.
attr
=
attr
;
this
.
server
=
server
;
this
.
sts
=
sts
;
}
public
boolean
evenSts
()
{
return
(
sts
%
2
==
0
);}
public
boolean
oddSts
()
{
return
(
sts
%
2
==
1
);}
public
int
getSts
()
{
return
sts
;}
}
java/jpwr/rt/src/makefile
View file @
50f2898b
...
...
@@ -36,6 +36,9 @@ local_java_sources = \
GdhrsAttrDef.java
\
CircBuffInfo.java
\
GdhrCircBuffInfo.java
\
GdhrGetDsTrend.java
\
GdhrSevItemInfo.java
\
GdhrSevItemData.java
\
GdhApplIfc.java
\
Gdh.java
\
Sub.java
\
...
...
java/jsw/cmn/src/gdh.jsi
View file @
50f2898b
This diff is collapsed.
Click to expand it.
java/jsw/cmn/src/glow.jsi
View file @
50f2898b
...
...
@@ -37,6 +37,8 @@ var Glow = {
eType_DynType2 : 22,
eType_ActionType2 : 23,
eType_AppMotion : 24,
eType_Float : 25,
eType_HorizDirection : 26,
eCtxType_Glow : 0,
eCtxType_Brow : 1,
...
...
@@ -125,6 +127,9 @@ var Glow = {
eDirection_Up : 3,
eDirection_Down : 4,
eHorizDirection_Left : 0,
eHorizDirection_Right : 1,
eAdjustment_Center : 0,
eAdjustment_Right : 1,
eAdjustment_Left : 2,
...
...
@@ -1260,16 +1265,17 @@ var Glow = {
eSave_GrowTrend_trace_data7 : 3223,
eSave_GrowTrend_trace_data8 : 3224,
eSave_GrowTrend_trace_data9 : 3225,
eSave_GrowTrend_trace_data10 : 3226,
eSave_GrowTrend_trace_data10
: 3226,
eSave_GrowTrend_access : 3227,
eSave_GrowTrend_cycle : 3228,
eSave_GrowTrend_cycle
: 3228,
eSave_GrowTrend_ref_object : 3229,
eSave_GrowTrend_userdata_cb : 3230,
eSave_GrowTrend_x_max_value_0 : 3231,
eSave_GrowTrend_x_min_value_0 : 3232,
eSave_GrowTrend_x_max_value_1 : 3233,
eSave_GrowTrend_x_min_value_1 : 3234,
eSave_GrowTrend_mode : 3235,
eSave_GrowTrend_mode : 3235,
eSave_GrowTrend_direction : 3236,
eSave_GrowSlider_grownode_part : 3300,
eSave_GrowSlider_direction : 3301,
eSave_GrowSlider_max_value : 3302,
...
...
@@ -9994,8 +10000,9 @@ function GrowTrend( ctx) {
this.x_mark2;
this.y_mark1;
this.y_mark2;
this.mark1_color;
this.mark2_color;
this.mark1_color = Glow.eDrawType_Inherit;
this.mark2_color = Glow.eDrawType_Inherit;
this.direction;
for ( var i = 0; i < Glow.TREND_MAX_CURVES; i++)
this.curve[i] = null;
...
...
@@ -10069,6 +10076,9 @@ function GrowTrend( ctx) {
case Glow.eSave_GrowTrend_curve_width:
this.curve_width = parseInt(tokens[1], 10);
break;
case Glow.eSave_GrowTrend_direction:
this.direction = parseInt(tokens[1], 10);
break;
case Glow.eSave_GrowTrend_scan_time:
this.scan_time = parseFloat( tokens[1]);
break;
...
...
@@ -10109,7 +10119,6 @@ function GrowTrend( ctx) {
if ( end)
break;
}
this.configure_curves();
return i;
};
...
...
@@ -10267,7 +10276,7 @@ function GrowTrend( ctx) {
if ( xm2 >= ll_x && xm2 <= ur_x) {
drawtype = this.mark2_color;
if ( drawtype == Glow.eDrawType_Inherit)
drawtype = Glow.eDrawType_Color
Yellow
;
drawtype = Glow.eDrawType_Color
Red
;
this.ctx.gdraw.line( xm2, ll_y, xm2, ur_y, drawtype, idx, 0);
}
}
...
...
@@ -10293,12 +10302,14 @@ function GrowTrend( ctx) {
if ( ym2 >= ll_y && ym2 <= ur_y) {
drawtype = this.mark2_color;
if ( drawtype == Glow.eDrawType_Inherit)
drawtype = Glow.eDrawType_Color
Yellow
;
drawtype = Glow.eDrawType_Color
Red
;
this.ctx.gdraw.line( ll_x, ym2, ur_x, ym2, drawtype, idx, 0);
}
}
if ( this.border !== 0) {
drawtype = GlowColor.get_drawtype( this.draw_type, Glow.eDrawType_LineHighlight,
highlight, colornode, 0, 0);
this.ctx.gdraw.rect( ll_x, ll_y, ur_x - ll_x, ur_y - ll_y, drawtype, idx, 0);
}
};
...
...
@@ -10381,7 +10392,7 @@ function GrowTrend( ctx) {
this.y_mark1 = this.ur.y - (mark - min) / (max - min) * (this.ur.y - this.ll.y);
}
if ( this.display_y_mark2 !== 0) {
mark = this.y_min_value[0] - (this.y_mark2 - ur.y) *(this.y_max_value[0] - this.y_min_value[0]) / (this.ur.y - this.ll.y);
mark = this.y_min_value[0] - (this.y_mark2 -
this.
ur.y) *(this.y_max_value[0] - this.y_min_value[0]) / (this.ur.y - this.ll.y);
this.y_mark2 = this.ur.y - (mark - min) / (max - min) * (this.ur.y - this.ll.y);
}
}
...
...
@@ -10463,6 +10474,100 @@ function GrowTrend( ctx) {
this.get_background_object_limits = function( t, type, x, y, bo) {
return 0;
};
this.get_direction = function() {
return this.direction;
};
this.set_data = function( tdata, vdata, curve_idx, data_points) {
var dt, dt_fill;
var points;
var cpoints;
var pointarray;
var point_p;
var i, j, idx;
this.no_of_points = Math.max( 2, this.no_of_points);
points = cpoints = Math.min( this.no_of_points, data_points);
if ( this.fill_curve !== 0)
cpoints += 2;
this.curve_width = Math.min( Glow.DRAW_TYPE_SIZE, Math.max( 1, this.curve_width));
pointarray = new Array(cpoints);
j = curve_idx;
for ( i = 0, idx = 0; i < cpoints; i++, idx++) {
point_p = pointarray[i] = new GlowPointX();
if ( this.fill_curve == 0) {
idx = i;
if ( this.y_max_value[j] != this.y_min_value[j])
point_p.y = this.ur.y - (vdata[idx] - this.y_min_value[j]) /
(this.y_max_value[j] - this.y_min_value[j]) * (this.ur.y - this.ll.y);
point_p.y = Math.max( this.ll.y, Math.min( point_p.y, this.ur.y));
if ( this.direction == Glow.eHorizDirection_Right)
point_p.x = this.ll.x
+ (tdata[idx] - tdata[0]) / (tdata[points - 1] - tdata[0])
* (this.ur.x - this.ll.x);
else
point_p.x = this.ur.x
- (tdata[idx] - tdata[0]) / (tdata[points - 1] - tdata[0])
* (this.ur.x - this.ll.x);
}
else {
if ( i == 0) {
if ( this.direction == Glow.eHorizDirection_Right)
point_p.x = this.ll.x;
else
point_p.x = this.ur.x;
point_p.y = this.ur.y;
idx--;
} else if (i == cpoints -1) {
if ( this.direction == Glow.eHorizDirection_Right)
point_p.x = this.ur.x;
else
point_p.x = this.ll.x;
point_p.y = this.ur.y;
} else {
if ( this.y_max_value[j] != this.y_min_value[j])
point_p.y = this.ur.y
- (vdata[idx] - this.y_min_value[j])
/ (this.y_max_value[j] - this.y_min_value[j]) * (this.ur.y - this.ll.y);
point_p.y = Math.max(this.ll.y, Math.min(point_p.y, this.ur.y));
if (this.direction == Glow.eHorizDirection_Right)
point_p.x = this.ll.x
+ (tdata[idx] - tdata[0]) / (tdata[points - 1] - tdata[0])
* (this.ur.x - this.ll.x);
else
point_p.x = this.ur.x
- (tdata[idx] - tdata[0]) / (tdata[points - 1] - tdata[0])
* (this.ur.x - this.ll.x);
}
}
point_p++;
}
if ( this.curve_drawtype[j] != Glow.eDrawType_Inherit)
dt = this.curve_drawtype[j];
else
dt = this.draw_type;
if ( this.curve_fill_drawtype[j] != Glow.eDrawType_Inherit)
dt_fill = this.curve_fill_drawtype[j];
else
dt_fill = this.draw_type;
this.ctx.nodraw++;
this.curve[j] = new GrowPolyline( ctx);
this.curve[j].init( "", pointarray, cpoints, dt,
this.curve_width,
0, this.fill_curve, 1, 0, dt_fill);
this.ctx.nodraw--;
this.draw();
};
}
GrowTrend.prototype = Object.create(GrowRect.prototype);
...
...
java/jsw/ge/src/ge.js
View file @
50f2898b
This diff is collapsed.
Click to expand it.
sev/lib/sev/src/sev_dbms.cpp
View file @
50f2898b
...
...
@@ -1417,7 +1417,6 @@ int sev_dbms::write_value(pwr_tStatus* sts, int item_idx, int attr_idx,
}
break
;
case
pwr_eType_UInt32
:
case
pwr_eType_Boolean
:
if
((
feqf
(
m_items
[
item_idx
].
deadband
,
0.0
f
)
&&
!
memcmp
(
buf
,
m_items
[
item_idx
].
old_value
,
sizeof
(
pwr_tUInt32
)))
...
...
@@ -1430,6 +1429,14 @@ int sev_dbms::write_value(pwr_tStatus* sts, int item_idx, int attr_idx,
*
(
pwr_tUInt32
*
)
m_items
[
item_idx
].
old_value
=
*
(
pwr_tUInt32
*
)
buf
;
}
break
;
case
pwr_eType_Boolean
:
if
(
*
(
pwr_tBoolean
*
)
buf
==
*
(
pwr_tBoolean
*
)
m_items
[
item_idx
].
old_value
)
{
return
1
;
}
else
{
m_items
[
item_idx
].
deadband_active
=
0
;
*
(
pwr_tBoolean
*
)
m_items
[
item_idx
].
old_value
=
*
(
pwr_tBoolean
*
)
buf
;
}
break
;
case
pwr_eType_UInt16
:
if
((
feqf
(
m_items
[
item_idx
].
deadband
,
0.0
f
)
&&
!
memcmp
(
...
...
src/lib/rt/src/rt_cbuf.c
View file @
50f2898b
...
...
@@ -440,7 +440,14 @@ pwr_tStatus cbuf_UpdateCircBuffInfo(cbuf_sCircBuffInfo* info, int infosize)
first_index
=
info
[
j
].
last_idx
;
last_index
=
hp
->
LastIndex
;
start_idx
=
last_index
-
info
[
j
].
samples
;
if
(
first_index
<
last_index
)
{
if
(
first_index
==
last_index
)
{
info
[
j
].
last_idx
=
last_index
;
info
[
j
].
first_idx
=
first_index
;
info
[
j
].
offset
=
0
;
info
[
j
].
size
=
0
;
break
;
}
else
if
(
first_index
<
last_index
)
{
if
(
first_index
>
start_idx
)
start_idx
=
first_index
;
}
else
{
...
...
wb/exp/wb/src/pwr_wb_palette.cnf
View file @
50f2898b
...
...
@@ -287,6 +287,7 @@ palette NavigatorPalette
class SysMonConfig
class WebHandler
class WebBrowserConfig
class WebSocketServer
}
menu IO
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment