@ -7,12 +7,18 @@ import { observer } from "mobx-react";
import * as config from "../config" ;
import * as config from "../config" ;
import { NavLink } from "react-router-dom" ;
import { NavLink } from "react-router-dom" ;
import * as comm from '@haina/utils-commons' ;
import * as comm from '@haina/utils-commons' ;
import { show _vs _tag } from './../utils/commons' ;
import { utils , writeFileXLSX } from "xlsx" ;
import DateGroupRadio from '../components/DateGroupRadio' ;
import DateGroupRadio from '../components/DateGroupRadio' ;
import SearchForm from './../components/search/SearchForm' ;
import SearchForm from './../components/search/SearchForm' ;
import { TableExportBtn } from './../components/Data' ;
import { TableExportBtn , VSDataTag } from './../components/Data' ;
import ParetoChart from "../components/Pareto" ;
import ParetoChart from "../components/Pareto" ;
import { toJS } from 'mobx' ;
const DataRenderCell = ( { data1 , data2 , dataSuffix = '' , showDiffData , ... props } ) => {
if ( showDiffData ) {
return < VSDataTag data1 = { data1 } data2 = { data2 } dataSuffix = { dataSuffix } { ...props } / > ;
}
return < div > { data1 } { dataSuffix } < / div > ;
} ;
class Orders extends Component {
class Orders extends Component {
static contextType = stores _Context ;
static contextType = stores _Context ;
@ -24,11 +30,38 @@ class Orders extends Component {
format _data ( data ) {
format _data ( data ) {
const { date _picker _store , orders _store } = this . context ;
const { date _picker _store , orders _store } = this . context ;
const result = { dataSource : [ ] , columns : [ ] } ;
const result = { dataSource : [ ] , columns : [ ] } ;
if ( ! comm . emptyValue ( data ) ) {
if ( ! comm . isEmpty ( data ) ) {
const rows1Map = data . ordercount1 . reduce ( ( a , row1 ) => ( { ... a , [ row1 . OrderTypeSN ] : row1 } ) , { } ) ;
const rows2Map = data . ordercount2 . reduce ( ( a , row2 ) => ( { ... a , [ row2 . OrderTypeSN ] : row2 } ) , { } ) ;
/ / D i f f : e l e m e n t s i n r o w s 2 b u t n o t i n r o w s 1
const diffKey = [ ... new Set ( Object . keys ( rows2Map ) . filter ( ( x ) => ! new Set ( Object . keys ( rows1Map ) ) . has ( x ) ) ) ] ;
const withDiff1 = ( structuredClone ( toJS ( data . ordercount1 ) ) || [ ] ) . map ( ( r1 ) => ( { ... r1 , diff : rows2Map [ r1 . OrderTypeSN ] } ) ) ;
withDiff1 . push (
... diffKey . map ( ( key ) => ( {
diff : rows2Map [ key ] ,
EOI _ObjSN : rows2Map [ key ] . EOI _ObjSN ,
OrderType : rows2Map [ key ] . OrderType ,
CJrate : 0 ,
CJCount _vs : - 100 ,
CJPersonNum _vs : - 100 ,
CJrate _vs : - 100 ,
YJLY _vs : - 100 ,
OrderCount _vs : - 100 ,
CJCount _diff : - rows2Map [ key ] . CJCount ,
CJPersonNum _diff : - rows2Map [ key ] . CJPersonNum ,
CJrate _diff : - rows2Map [ key ] . CJrate ,
YJLY _diff : - rows2Map [ key ] . YJLY ,
OrderCount _diff : - rows2Map [ key ] . OrderCount ,
Ordervalue : 0 ,
Ordervalue _diff : - rows2Map [ key ] . Ordervalue ,
Ordervalue _vs : - 100 ,
} ) )
) ;
const showDiff = date _picker _store . start _date _cp && date _picker _store . end _date _cp ;
result . dataSource = withDiff1 ;
const ordercountTotal1 = data . ordercountTotal1 ;
const ordercountTotal1 = data . ordercountTotal1 ;
const ordercountTotal2 = data . ordercountTotal2 ;
const ordercountTotal2 = data . ordercountTotal2 ;
if ( date _picker _store . start _date _cp && date _picker _store . end _date _cp ) {
/ / 有 比 较 的 数 据
result . columns = [
result . columns = [
{
{
title : '#' ,
title : '#' ,
@ -40,14 +73,14 @@ class Orders extends Component {
< div >
< div >
{ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date . format ( config . DATE _FORMAT ) }
{ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date . format ( config . DATE _FORMAT ) }
< / div >
< / div >
< div >
{ showDiff ? < div >
{ date _picker _store . start _date _cp . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date _cp . format ( config . DATE _FORMAT ) }
{ date _picker _store . start _date _cp . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date _cp . format ( config . DATE _FORMAT ) }
< / div >
< / div > : null }
< / span >
< / span >
) ,
) ,
titleX : ` ${ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ ${ date _picker _store . end _date . format ( config . DATE _FORMAT ) } vs ${ date _picker _store . start _date _cp . format (
titleX : showDiff ? ` ${ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ ${ date _picker _store . end _date . format ( config . DATE _FORMAT ) } vs ${ date _picker _store . start _date _cp . format (
config . DATE _FORMAT
config . DATE _FORMAT
) } ~ $ { date _picker _store . end _date _cp . format ( config . DATE _FORMAT ) } ` ,
) } ~ $ { date _picker _store . end _date _cp . format ( config . DATE _FORMAT ) } ` : ` $ { date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ $ { date _picker _store . end _date . format ( config . DATE _FORMAT ) } ` ,
dataIndex : 'OrderType' ,
dataIndex : 'OrderType' ,
fixed : 'left' ,
fixed : 'left' ,
render : ( text , record ) => < NavLink to = { ` /orders_sub/ ${ orders _store . active _tab _key } / ${ record . OrderTypeSN } / ${ encodeURIComponent ( record . OrderType ) } ` } > { text } < / NavLink > ,
render : ( text , record ) => < NavLink to = { ` /orders_sub/ ${ orders _store . active _tab _key } / ${ record . OrderTypeSN } / ${ encodeURIComponent ( record . OrderType ) } ` } > { text } < / NavLink > ,
@ -58,9 +91,18 @@ class Orders extends Component {
title : '数量' ,
title : '数量' ,
children : [
children : [
{
{
title : show _vs _tag ( ordercountTotal1 . OrderCount _vs , ordercountTotal1 . OrderCount _diff , ordercountTotal1 . OrderCount , ordercountTotal2 . OrderCount ) ,
title : (
< DataRenderCell
showDiffData = { showDiff }
data1 = { ordercountTotal1 ? . OrderCount }
data2 = { ordercountTotal2 ? . OrderCount }
diffPercent = { ordercountTotal1 ? . OrderCount _vs }
diffData = { ordercountTotal1 ? . OrderCount _diff }
/ >
) ,
titleX : [ ordercountTotal1 . OrderCount , ordercountTotal2 . OrderCount ] . join ( ' vs ' ) ,
titleX : [ ordercountTotal1 . OrderCount , ordercountTotal2 . OrderCount ] . join ( ' vs ' ) ,
dataIndex : 'OrderCount' ,
dataIndex : 'OrderCount' ,
render : ( text , r ) => < DataRenderCell showDiffData = { showDiff } data1 = { text } data2 = { r . diff ? . OrderCount } diffPercent = { r . OrderCount _vs } diffData = { r . OrderCount _diff } / > ,
} ,
} ,
] ,
] ,
} ,
} ,
@ -68,9 +110,18 @@ class Orders extends Component {
title : '成交数' ,
title : '成交数' ,
children : [
children : [
{
{
title : show _vs _tag ( ordercountTotal1 . CJCount _vs , ordercountTotal1 . CJCount _diff , ordercountTotal1 . CJCount , ordercountTotal2 . CJCount ) ,
title : (
< DataRenderCell
showDiffData = { showDiff }
data1 = { ordercountTotal1 ? . CJCount }
data2 = { ordercountTotal2 ? . CJCount }
diffPercent = { ordercountTotal1 ? . CJCount _vs }
diffData = { ordercountTotal1 ? . CJCount _diff }
/ >
) ,
titleX : [ ordercountTotal1 . CJCount , ordercountTotal2 . CJCount ] . join ( ' vs ' ) ,
titleX : [ ordercountTotal1 . CJCount , ordercountTotal2 . CJCount ] . join ( ' vs ' ) ,
dataIndex : 'CJCount' ,
dataIndex : 'CJCount' ,
render : ( text , r ) => < DataRenderCell showDiffData = { showDiff } data1 = { text } data2 = { r . diff ? . CJCount } diffPercent = { r . CJCount _vs } diffData = { r . CJCount _diff } / > ,
} ,
} ,
] ,
] ,
} ,
} ,
@ -78,9 +129,18 @@ class Orders extends Component {
title : '成交人数' ,
title : '成交人数' ,
children : [
children : [
{
{
title : show _vs _tag ( ordercountTotal1 . CJPersonNum _vs , ordercountTotal1 . CJPersonNum _diff , ordercountTotal1 . CJPersonNum , ordercountTotal2 . CJPersonNum ) ,
title : (
< DataRenderCell
showDiffData = { showDiff }
data1 = { ordercountTotal1 ? . CJPersonNum }
data2 = { ordercountTotal2 ? . CJPersonNum }
diffPercent = { ordercountTotal1 ? . CJPersonNum _vs }
diffData = { ordercountTotal1 ? . CJPersonNum _diff }
/ >
) ,
titleX : [ ordercountTotal1 . CJPersonNum , ordercountTotal2 . CJPersonNum ] . join ( ' vs ' ) ,
titleX : [ ordercountTotal1 . CJPersonNum , ordercountTotal2 . CJPersonNum ] . join ( ' vs ' ) ,
dataIndex : 'CJPersonNum' ,
dataIndex : 'CJPersonNum' ,
render : ( text , r ) => < DataRenderCell showDiffData = { showDiff } data1 = { text } data2 = { r . diff ? . CJPersonNum } diffPercent = { r . CJPersonNum _vs } diffData = { r . CJPersonNum _diff } / > ,
} ,
} ,
] ,
] ,
} ,
} ,
@ -88,9 +148,18 @@ class Orders extends Component {
title : '成交率' ,
title : '成交率' ,
children : [
children : [
{
{
title : show _vs _tag ( ordercountTotal1 . CJrate _vs , ordercountTotal1 . CJrate _diff , ordercountTotal1 . CJrate , ordercountTotal2 . CJrate ) ,
title : (
< DataRenderCell
showDiffData = { showDiff }
data1 = { ordercountTotal1 ? . CJrate }
data2 = { ordercountTotal2 ? . CJrate }
diffPercent = { ordercountTotal1 ? . CJrate _vs }
diffData = { ordercountTotal1 ? . CJrate _diff }
/ >
) ,
titleX : [ ordercountTotal1 . CJrate , ordercountTotal2 . CJrate ] . join ( ' vs ' ) ,
titleX : [ ordercountTotal1 . CJrate , ordercountTotal2 . CJrate ] . join ( ' vs ' ) ,
dataIndex : 'CJrate' ,
dataIndex : 'CJrate' ,
render : ( text , r ) => < DataRenderCell showDiffData = { showDiff } data1 = { text } data2 = { r . diff ? . CJrate } diffPercent = { r . CJrate _vs } diffData = { r . CJrate _diff } / > ,
} ,
} ,
] ,
] ,
} ,
} ,
@ -98,9 +167,18 @@ class Orders extends Component {
title : '成交毛利(预计)' ,
title : '成交毛利(预计)' ,
children : [
children : [
{
{
title : show _vs _tag ( ordercountTotal1 . YJLY _vs , ordercountTotal1 . YJLY _diff , ordercountTotal1 . YJLY , ordercountTotal2 . YJLY ) ,
title : (
< DataRenderCell
showDiffData = { showDiff }
data1 = { ordercountTotal1 ? . YJLY }
data2 = { ordercountTotal2 ? . YJLY }
diffPercent = { ordercountTotal1 ? . YJLY _vs }
diffData = { ordercountTotal1 ? . YJLY _diff }
/ >
) ,
titleX : [ ordercountTotal1 . YJLY , ordercountTotal2 . YJLY ] . join ( ' vs ' ) ,
titleX : [ ordercountTotal1 . YJLY , ordercountTotal2 . YJLY ] . join ( ' vs ' ) ,
dataIndex : 'YJLY' ,
dataIndex : 'YJLY' ,
render : ( text , r ) => < DataRenderCell showDiffData = { showDiff } data1 = { text } data2 = { r . diff ? . YJLY } diffPercent = { r . YJLY _vs } diffData = { r . YJLY _diff } / > ,
} ,
} ,
] ,
] ,
} ,
} ,
@ -109,144 +187,24 @@ class Orders extends Component {
title : '单个订单价值' ,
title : '单个订单价值' ,
children : [
children : [
{
{
title : show _vs _tag ( ordercountTotal1 . Ordervalue _vs , ordercountTotal1 . Ordervalue _diff , ordercountTotal1 . Ordervalue , ordercountTotal2 . Ordervalue ) ,
title : (
< DataRenderCell
showDiffData = { showDiff }
data1 = { ordercountTotal1 ? . Ordervalue }
data2 = { ordercountTotal2 ? . Ordervalue }
diffPercent = { ordercountTotal1 ? . Ordervalue _vs }
diffData = { ordercountTotal1 ? . Ordervalue _diff }
/ >
) ,
titleX : [ ordercountTotal1 . Ordervalue , ordercountTotal2 . Ordervalue ] . join ( ' vs ' ) ,
titleX : [ ordercountTotal1 . Ordervalue , ordercountTotal2 . Ordervalue ] . join ( ' vs ' ) ,
dataIndex : 'Ordervalue' ,
dataIndex : 'Ordervalue' ,
render : ( text , r ) => < DataRenderCell showDiffData = { showDiff } data1 = { text } data2 = { r . diff ? . Ordervalue } diffPercent = { r . Ordervalue _vs } diffData = { r . Ordervalue _diff } / > ,
} ,
} ,
] ,
] ,
} ,
} ,
] ;
] ;
/ / 1 . 找 出 两 个 数 组 O r d e r T y p e 相 同 的 数 据 做 比 较 显 示 2 . 找 出 两 组 数 据 O r d e r T y p e 都 不 相 同 的 数 据 做 显 示
return result ;
let has _same _type = false ; / / 数 组 1 在 数 组 2 中 是 否 找 到 相 同 的 类 型
for ( const item of data . ordercount1 ) {
has _same _type = false ;
/ / 数 组 1 在 数 组 2 中 相 同 的 类 型
for ( const item2 of data . ordercount2 ) {
if ( item . OrderType === item2 . OrderType ) {
has _same _type = true ;
result . dataSource . push ( {
key : item . key ,
OrderType : item . OrderType ,
OrderTypeSN : item . OrderTypeSN ,
OrderCount : show _vs _tag ( item . OrderCount _vs , item . OrderCount _diff , item . OrderCount , item2 . OrderCount ) ,
OrderCount _X : ( [ item . OrderCount , item2 . OrderCount ] . join ( ' vs ' ) ) ,
CJCount : show _vs _tag ( item . CJCount _vs , item . CJCount _diff , item . CJCount , item2 . CJCount ) ,
CJCount _X : ( [ item . CJCount , item2 . CJCount ] . join ( ' vs ' ) ) ,
CJPersonNum : show _vs _tag ( item . CJPersonNum _vs , item . CJPersonNum _diff , item . CJPersonNum , item2 . CJPersonNum ) ,
CJPersonNum _X : ( [ item . CJPersonNum , item2 . CJPersonNum ] . join ( ' vs ' ) ) ,
CJrate : show _vs _tag ( item . CJrate _vs , item . CJrate _diff , item . CJrate , item2 . CJrate ) ,
CJrate _X : ( [ item . CJrate , item2 . CJrate ] . join ( ' vs ' ) ) ,
YJLY : show _vs _tag ( item . YJLY _vs , item . YJLY _diff , item . YJLY , item2 . YJLY ) ,
YJLY _X : ( [ item . YJLY , item2 . YJLY ] . join ( ' vs ' ) ) ,
Ordervalue : show _vs _tag ( item . Ordervalue _vs , item . Ordervalue _diff , item . Ordervalue , item2 . Ordervalue ) ,
Ordervalue _X : ( [ item . Ordervalue , item2 . Ordervalue ] . join ( ' vs ' ) ) ,
} ) ;
}
}
/ / 数 组 1 中 不 在 数 组 2 的 类 型
if ( has _same _type === false ) {
result . dataSource . push ( {
key : item . key ,
OrderType : item . OrderType ,
OrderTypeSN : item . OrderTypeSN ,
OrderCount : show _vs _tag ( comm . formatPercent ( item . OrderCount ) , item . OrderCount , item . OrderCount , 0 ) ,
OrderCount _X : ( [ item . OrderCount , 0 ] . join ( ' vs ' ) ) ,
CJCount : show _vs _tag ( comm . formatPercent ( item . CJCount ) , item . CJCount , item . CJCount , 0 ) ,
CJCount _X : ( [ item . CJCount , 0 ] . join ( ' vs ' ) ) ,
CJPersonNum : show _vs _tag ( comm . formatPercent ( item . CJPersonNum ) , item . CJPersonNum , item . CJPersonNum , 0 ) ,
CJPersonNum _X : ( [ item . CJPersonNum , 0 ] . join ( ' vs ' ) ) ,
CJrate : show _vs _tag ( item . CJrate , item . CJrate , item . CJrate , 0 ) ,
CJrate _X : ( [ item . CJrate , 0 ] . join ( ' vs ' ) ) ,
YJLY : show _vs _tag ( comm . formatPercent ( item . YJLY ) , item . YJLY , item . YJLY , 0 ) ,
YJLY _X : ( [ item . YJLY , 0 ] . join ( ' vs ' ) ) ,
Ordervalue : show _vs _tag ( comm . formatPercent ( item . Ordervalue ) , item . Ordervalue , item . Ordervalue , 0 ) ,
Ordervalue _X : ( [ item . Ordervalue , 0 ] . join ( ' vs ' ) ) ,
} ) ;
}
}
/ / 数 组 2 中 不 在 数 组 1 的 类 型
for ( const item2 of data . ordercount2 ) {
has _same _type = false ;
for ( const item of data . ordercount1 ) {
if ( item . OrderType === item2 . OrderType ) {
has _same _type = true ;
}
}
if ( has _same _type === false ) {
result . dataSource . push ( {
key : item2 . key ,
OrderType : item2 . OrderType ,
OrderTypeSN : item2 . OrderTypeSN ,
OrderCount : show _vs _tag ( comm . formatPercent ( - item2 . OrderCount ) , - item2 . OrderCount , 0 , item2 . OrderCount ) ,
OrderCount _X : ( [ 0 , item2 . OrderCount ] . join ( ' vs ' ) ) ,
CJCount : show _vs _tag ( comm . formatPercent ( - item2 . CJCount ) , - item2 . CJCount , 0 , item2 . CJCount ) ,
CJCount _X : ( [ 0 , item2 . CJCount ] . join ( ' vs ' ) ) ,
CJPersonNum : show _vs _tag ( comm . formatPercent ( - item2 . CJPersonNum ) , - item2 . CJPersonNum , 0 , item2 . CJPersonNum ) ,
CJPersonNum _X : ( [ 0 , item2 . CJPersonNum ] . join ( ' vs ' ) ) ,
CJrate : show _vs _tag ( - item2 . CJrate , - item2 . CJrate , 0 , item2 . CJrate ) ,
CJrate _X : ( [ 0 , item2 . CJrate ] . join ( ' vs ' ) ) ,
YJLY : show _vs _tag ( comm . formatPercent ( - item2 . YJLY ) , - item2 . YJLY , 0 , item2 . YJLY ) ,
YJLY _X : ( [ 0 , item2 . YJLY ] . join ( ' vs ' ) ) ,
Ordervalue : show _vs _tag ( comm . formatPercent ( - item2 . Ordervalue ) , - item2 . Ordervalue , 0 , item2 . Ordervalue ) ,
Ordervalue _X : ( [ 0 , item2 . Ordervalue ] . join ( ' vs ' ) ) ,
} ) ;
}
}
} else {
result . columns = [
{
title : "#" ,
fixed : 'left' ,
children : [
{
title : (
< span >
< div >
{ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ { date _picker _store . end _date . format ( config . DATE _FORMAT ) }
< / div >
< / span >
) ,
titleX : ` ${ date _picker _store . start _date . format ( config . DATE _FORMAT ) } ~ ${ date _picker _store . end _date . format ( config . DATE _FORMAT ) } ` ,
fixed : 'left' ,
dataIndex : "OrderType" ,
render : ( text , record ) => < NavLink to = { ` /orders_sub/ ${ orders _store . active _tab _key } / ${ record . OrderTypeSN } / ${ encodeURIComponent ( record . OrderType ) } ` } > { text } < / NavLink > ,
} ,
] ,
} ,
{
title : "数量" ,
children : [ { title : ordercountTotal1 . OrderCount , dataIndex : "OrderCount" } ] ,
sorter : ( a , b ) => b . OrderCount - a . OrderCount ,
} ,
{
title : "成交数" ,
children : [ { title : ordercountTotal1 . CJCount , dataIndex : "CJCount" } ] ,
sorter : ( a , b ) => b . CJCount - a . CJCount ,
} ,
{
title : "成交人数" ,
children : [ { title : ordercountTotal1 . CJPersonNum , dataIndex : "CJPersonNum" } ] ,
sorter : ( a , b ) => b . CJPersonNum - a . CJPersonNum ,
} ,
{
title : "成交率" ,
children : [ { title : ordercountTotal1 . CJrate , dataIndex : "CJrate" } ] ,
sorter : ( a , b ) => parseInt ( b . CJrate ) - parseInt ( a . CJrate ) ,
} ,
{
title : "成交毛利(预计)" ,
children : [ { title : ordercountTotal1 . YJLY , dataIndex : "YJLY" } ] ,
sorter : ( a , b ) => parseFloat ( b . YJLY . replace ( /,/g , "" ) ) - parseFloat ( a . YJLY . replace ( /,/g , "" ) ) ,
} ,
{
title : "单个订单价值" ,
children : [ { title : ordercountTotal1 . Ordervalue , dataIndex : "Ordervalue" } ] ,
sorter : ( a , b ) => parseFloat ( b . Ordervalue . replace ( /,/g , "" ) ) - parseFloat ( a . Ordervalue . replace ( /,/g , "" ) ) ,
} ,
] ;
result . dataSource = data . ordercount1 ;
}
}
}
return result ;
return result ;
}
}
@ -256,10 +214,10 @@ class Orders extends Component {
const table _data = orders _store . orderCountData _Form ? this . format _data ( orders _store . orderCountData _Form ) : [ ] ;
const table _data = orders _store . orderCountData _Form ? this . format _data ( orders _store . orderCountData _Form ) : [ ] ;
const data _source = orders _store . orderCountData ? orders _store . orderCountData : [ ] ;
const data _source = orders _store . orderCountData ? orders _store . orderCountData : [ ] ;
const avg _line _y = Math . round ( orders _store . avgLine1 ) ;
const avg _line _y = Math . round ( orders _store . avgLine1 ) ;
const pie _data = comm . emptyValue ( orders _store . orderCountData _Form )
const pie _data = comm . isEmpty ( orders _store . orderCountData _Form )
? [ ]
? [ ]
: orders _store . orderCountData _Form . ordercount1 . map ( ( ele ) => ( { ... ele , YJLYx : comm . price _to _number ( ele . YJLY ) } ) ) ; / / 饼 图 的 显 示
: orders _store . orderCountData _Form . ordercount1 . map ( ( ele ) => ( { ... ele , YJLYx : comm . price _to _number ( ele . YJLY ) } ) ) ; / / 饼 图 的 显 示
const pie _data2 = comm . emptyValue ( orders _store . orderCountData _Form )
const pie _data2 = comm . isEmpty ( orders _store . orderCountData _Form )
? [ ]
? [ ]
: orders _store . orderCountData _Form . ordercount2 . map ( ( ele ) => ( { ... ele , YJLYx : comm . price _to _number ( ele . YJLY ) } ) ) ;
: orders _store . orderCountData _Form . ordercount2 . map ( ( ele ) => ( { ... ele , YJLYx : comm . price _to _number ( ele . YJLY ) } ) ) ;