Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F83674466
DifferentialReviewerStats.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Sep 18, 10:42
Size
7 KB
Mime Type
text/x-php
Expires
Fri, Sep 20, 10:42 (2 d)
Engine
blob
Format
Raw Data
Handle
20876748
Attached To
rPH Phabricator
DifferentialReviewerStats.php
View Options
<?php
/*
* Copyright 2012 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
final
class
DifferentialReviewerStats
{
private
$since
=
0
;
private
$until
;
public
function
setSince
(
$value
)
{
$this
->
since
=
$value
;
return
$this
;
}
public
function
setUntil
(
$value
)
{
$this
->
until
=
$value
;
return
$this
;
}
/**
* @return array($reviewed, $not_reviewed)
*/
public
function
computeTimes
(
DifferentialRevision
$revision
,
array
$comments
)
{
assert_instances_of
(
$comments
,
'DifferentialComment'
);
$add_rev
=
DifferentialComment
::
METADATA_ADDED_REVIEWERS
;
$rem_rev
=
DifferentialComment
::
METADATA_REMOVED_REVIEWERS
;
$date
=
$revision
->
getDateCreated
();
// Find out original reviewers.
$reviewers
=
array_fill_keys
(
$revision
->
getReviewers
(),
$date
);
foreach
(
array_reverse
(
$comments
)
as
$comment
)
{
$metadata
=
$comment
->
getMetadata
();
foreach
(
idx
(
$metadata
,
$add_rev
,
array
())
as
$phid
)
{
unset
(
$reviewers
[
$phid
]);
}
foreach
(
idx
(
$metadata
,
$rem_rev
,
array
())
as
$phid
)
{
$reviewers
[
$phid
]
=
$date
;
}
}
$reviewed
=
array
();
$not_reviewed
=
array
();
$status
=
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
;
foreach
(
$comments
as
$comment
)
{
$date
=
$comment
->
getDateCreated
();
$old_status
=
$status
;
switch
(
$comment
->
getAction
())
{
case
DifferentialAction
::
ACTION_UPDATE
:
if
(
$status
!=
ArcanistDifferentialRevisionStatus
::
CLOSED
&&
$status
!=
ArcanistDifferentialRevisionStatus
::
ACCEPTED
)
{
$status
=
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
;
}
break
;
case
DifferentialAction
::
ACTION_REQUEST
:
case
DifferentialAction
::
ACTION_RECLAIM
:
$status
=
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
;
break
;
case
DifferentialAction
::
ACTION_REJECT
:
case
DifferentialAction
::
ACTION_RETHINK
:
$status
=
ArcanistDifferentialRevisionStatus
::
NEEDS_REVISION
;
break
;
case
DifferentialAction
::
ACTION_ACCEPT
:
$status
=
ArcanistDifferentialRevisionStatus
::
ACCEPTED
;
break
;
case
DifferentialAction
::
ACTION_CLOSE
:
$status
=
ArcanistDifferentialRevisionStatus
::
CLOSED
;
break
;
case
DifferentialAction
::
ACTION_ABANDON
:
$status
=
ArcanistDifferentialRevisionStatus
::
ABANDONED
;
break
;
}
// Update current reviewers.
$metadata
=
$comment
->
getMetadata
();
foreach
(
idx
(
$metadata
,
$add_rev
,
array
())
as
$phid
)
{
// If someone reviewed a revision without being its reviewer then give
// him zero response time.
$reviewers
[
$phid
]
=
$date
;
}
foreach
(
idx
(
$metadata
,
$rem_rev
,
array
())
as
$phid
)
{
$start
=
idx
(
$reviewers
,
$phid
);
if
(
$start
!==
null
)
{
if
(
$date
>=
$this
->
since
)
{
$reviewed
[
$phid
][]
=
$date
-
$start
;
}
unset
(
$reviewers
[
$phid
]);
}
}
// TODO: Respect workdays and status away.
if
(
$old_status
!=
$status
)
{
if
(
$status
==
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
)
{
$reviewers
=
array_fill_keys
(
array_keys
(
$reviewers
),
$date
);
}
else
if
(
$date
>=
$this
->
since
)
{
if
(
$old_status
==
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
)
{
foreach
(
$reviewers
as
$phid
=>
$start
)
{
if
(
$phid
==
$comment
->
getAuthorPHID
())
{
$reviewed
[
$phid
][]
=
$date
-
$start
;
}
else
{
$not_reviewed
[
$phid
][]
=
$date
-
$start
;
}
}
}
}
}
}
if
(
$status
==
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
)
{
$date
=
(
$this
->
until
!==
null
?
$this
->
until
:
time
());
if
(
$date
>=
$this
->
since
)
{
foreach
(
$reviewers
as
$phid
=>
$start
)
{
$not_reviewed
[
$phid
][]
=
$date
-
$start
;
}
}
}
return
array
(
$reviewed
,
$not_reviewed
);
}
public
function
loadAvgs
()
{
$limit
=
1000
;
$conn_r
=
id
(
new
DifferentialRevision
())->
establishConnection
(
'r'
);
$sums
=
array
();
$counts
=
array
();
$all_not_reviewed
=
array
();
$last_id
=
0
;
do
{
$where
=
''
;
if
(
$this
->
until
!==
null
)
{
$where
.=
qsprintf
(
$conn_r
,
' AND dateCreated < %d'
,
$this
->
until
);
}
if
(
$this
->
since
)
{
$where
.=
qsprintf
(
$conn_r
,
' AND (dateModified > %d OR status = %s)'
,
$this
->
since
,
ArcanistDifferentialRevisionStatus
::
NEEDS_REVIEW
);
}
$revisions
=
id
(
new
DifferentialRevision
())->
loadAllWhere
(
'id > %d%Q ORDER BY id LIMIT %d'
,
$last_id
,
$where
,
$limit
);
if
(!
$revisions
)
{
break
;
}
$last_id
=
last_key
(
$revisions
);
$relations
=
queryfx_all
(
$conn_r
,
'SELECT * FROM %T WHERE revisionID IN (%Ld) AND relation = %s'
,
DifferentialRevision
::
RELATIONSHIP_TABLE
,
array_keys
(
$revisions
),
DifferentialRevision
::
RELATION_REVIEWER
);
$relations
=
igroup
(
$relations
,
'revisionID'
);
$where
=
''
;
if
(
$this
->
until
!==
null
)
{
$where
=
qsprintf
(
$conn_r
,
' AND dateCreated < %d'
,
$this
->
until
);
}
$all_comments
=
id
(
new
DifferentialComment
())->
loadAllWhere
(
'revisionID IN (%Ld)%Q ORDER BY revisionID, id'
,
array_keys
(
$revisions
),
$where
);
$all_comments
=
mgroup
(
$all_comments
,
'getRevisionID'
);
foreach
(
$revisions
as
$id
=>
$revision
)
{
$revision
->
attachRelationships
(
idx
(
$relations
,
$id
,
array
()));
$comments
=
idx
(
$all_comments
,
$id
,
array
());
list
(
$reviewed
,
$not_reviewed
)
=
$this
->
computeTimes
(
$revision
,
$comments
);
foreach
(
$reviewed
as
$phid
=>
$times
)
{
$sums
[
$phid
]
=
idx
(
$sums
,
$phid
,
0
)
+
array_sum
(
$times
);
$counts
[
$phid
]
=
idx
(
$counts
,
$phid
,
0
)
+
count
(
$times
);
}
foreach
(
$not_reviewed
as
$phid
=>
$times
)
{
$all_not_reviewed
[
$phid
][]
=
$times
;
}
}
}
while
(
count
(
$revisions
)
>=
$limit
);
foreach
(
$all_not_reviewed
as
$phid
=>
$not_reviewed
)
{
if
(!
array_key_exists
(
$phid
,
$counts
))
{
// If the person didn't make any reviews than take maximum time because
// he is at least that slow.
$sums
[
$phid
]
=
max
(
array_map
(
'max'
,
$not_reviewed
));
$counts
[
$phid
]
=
1
;
continue
;
}
$avg
=
$sums
[
$phid
]
/
$counts
[
$phid
];
foreach
(
$not_reviewed
as
$times
)
{
foreach
(
$times
as
$time
)
{
// Don't shorten the average time just because the reviewer was lucky
// to be in a group with someone faster.
if
(
$time
>
$avg
)
{
$sums
[
$phid
]
+=
$time
;
$counts
[
$phid
]++;
}
}
}
}
$avgs
=
array
();
foreach
(
$sums
as
$phid
=>
$sum
)
{
$avgs
[
$phid
]
=
$sum
/
$counts
[
$phid
];
}
return
$avgs
;
}
}
Event Timeline
Log In to Comment