2018-06-12 16:51:58 +00:00
/* SleepLib Day Class Implementation
2014-04-09 21:01:57 +00:00
*
2018-04-02 02:08:32 +00:00
* Copyright ( c ) 2011 - 2018 Mark Watkins < mark @ jedimark . net >
2014-04-09 21:01:57 +00:00
*
* This file is subject to the terms and conditions of the GNU General Public
2018-06-04 20:48:38 +00:00
* License . See the file COPYING in the main directory of the source code
* for more details . */
2011-06-26 08:30:44 +00:00
2012-01-24 15:51:11 +00:00
# include <QMultiMap>
2014-04-22 21:04:59 +00:00
2012-01-01 15:47:21 +00:00
# include <algorithm>
2014-04-22 21:04:59 +00:00
# include <cmath>
# include <limits>
2018-04-25 10:34:23 +00:00
# include <QDebug>
2014-04-22 21:04:59 +00:00
# include "day.h"
# include "profiles.h"
2011-06-26 08:30:44 +00:00
2014-08-20 17:17:13 +00:00
Day : : Day ( )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
d_firstsession = true ;
2014-09-11 14:23:08 +00:00
d_summaries_open = false ;
d_events_open = false ;
d_invalidate = true ;
2011-06-26 08:30:44 +00:00
}
Day : : ~ Day ( )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
delete sess ;
2011-06-26 08:30:44 +00:00
}
}
2014-08-20 17:17:13 +00:00
2014-09-11 14:23:08 +00:00
void Day : : updateCPAPCache ( )
{
d_count . clear ( ) ;
d_sum . clear ( ) ;
OpenSummary ( ) ;
QList < ChannelID > channels = getSortedMachineChannels ( MT_CPAP , schema : : FLAG | schema : : MINOR_FLAG | schema : : SPAN ) ;
2018-05-05 21:58:11 +00:00
for ( const auto code : channels ) {
2014-09-11 14:23:08 +00:00
d_count [ code ] = count ( code ) ;
d_sum [ code ] = count ( code ) ;
d_machhours [ MT_CPAP ] = hours ( MT_CPAP ) ;
}
}
2014-08-20 17:17:13 +00:00
Session * Day : : firstSession ( MachineType type )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
2014-08-20 17:17:13 +00:00
if ( ! sess - > enabled ( ) ) continue ;
2014-09-17 06:12:38 +00:00
if ( sess - > type ( ) = = type ) {
2014-08-20 17:17:13 +00:00
return sess ;
}
}
return nullptr ;
}
bool Day : : addMachine ( Machine * mach )
2011-06-26 08:30:44 +00:00
{
2014-09-11 14:23:08 +00:00
invalidate ( ) ;
2014-08-20 17:17:13 +00:00
if ( ! machines . contains ( mach - > type ( ) ) ) {
machines [ mach - > type ( ) ] = mach ;
return true ;
}
return false ;
2011-11-21 10:20:11 +00:00
}
2014-08-20 17:17:13 +00:00
Machine * Day : : machine ( MachineType type )
{
2018-05-05 21:58:11 +00:00
auto it = machines . find ( type ) ;
2014-08-20 17:17:13 +00:00
if ( it ! = machines . end ( ) )
return it . value ( ) ;
return nullptr ;
}
2014-08-21 05:46:14 +00:00
QList < Session * > Day : : getSessions ( MachineType type , bool ignore_enabled )
2014-08-20 17:17:13 +00:00
{
QList < Session * > newlist ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( ! ignore_enabled & & ! sess - > enabled ( ) )
2014-08-20 17:17:13 +00:00
continue ;
2018-05-05 21:58:11 +00:00
if ( sess - > type ( ) = = type )
newlist . append ( sess ) ;
2014-08-20 17:17:13 +00:00
}
return newlist ;
}
2014-04-17 05:58:57 +00:00
Session * Day : : find ( SessionID sessid )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > session ( ) = = sessid ) {
return sess ;
2014-04-17 05:58:57 +00:00
}
2011-12-27 13:21:10 +00:00
}
2014-04-23 13:19:56 +00:00
return nullptr ;
2011-12-27 13:21:10 +00:00
}
2011-06-26 08:30:44 +00:00
2014-08-20 17:17:13 +00:00
void Day : : addSession ( Session * s )
2011-06-26 08:30:44 +00:00
{
2018-04-25 10:34:23 +00:00
if ( s = = nullptr ) {
qDebug ( ) < < " addSession called with null session pointer " ;
return ;
}
2014-09-11 14:23:08 +00:00
invalidate ( ) ;
2018-05-05 21:58:11 +00:00
auto mi = machines . find ( s - > type ( ) ) ;
2014-08-20 17:17:13 +00:00
if ( mi ! = machines . end ( ) ) {
if ( mi . value ( ) ! = s - > machine ( ) ) {
2019-06-25 13:23:04 +00:00
qDebug ( ) < < " OSCAR can't add session " < < s - > session ( )
< < " [ " + QDateTime : : fromTime_t ( s - > session ( ) ) . toString ( " MMM dd, yyyy hh:mm:ss " ) + " ] "
< < " from machine " < < mi . value ( ) - > serial ( ) < < " to machine " < < s - > machine ( ) - > serial ( )
< < " to this day record, as it already contains a different machine of the same MachineType " < < s - > type ( ) ;
2014-08-20 17:17:13 +00:00
return ;
}
} else {
2014-09-17 06:12:38 +00:00
machines [ s - > type ( ) ] = s - > machine ( ) ;
2011-06-26 08:30:44 +00:00
}
2014-04-17 05:58:57 +00:00
2019-06-25 13:23:04 +00:00
if ( s - > first ( ) = = 0 )
2019-06-29 02:51:14 +00:00
qWarning ( ) < < " Day::addSession discarding session " < < s - > session ( )
2019-06-25 13:23:04 +00:00
< < " [ " + QDateTime : : fromTime_t ( s - > session ( ) ) . toString ( " MMM dd, yyyy hh:mm:ss " ) + " ] "
< < " from machine " < < s - > machine ( ) - > serial ( ) < < " with first=0 " ;
else
sessions . push_back ( s ) ;
2011-06-26 08:30:44 +00:00
}
2019-06-25 13:23:04 +00:00
2014-08-11 18:29:44 +00:00
EventDataType Day : : calcMiddle ( ChannelID code )
{
int c = p_profile - > general - > prefCalcMiddle ( ) ;
if ( c = = 0 ) {
return percentile ( code , 0.5 ) ; // Median
} else if ( c = = 1 ) {
return wavg ( code ) ; // Weighted Average
} else {
return avg ( code ) ; // Average
}
}
EventDataType Day : : calcMax ( ChannelID code )
{
2016-03-04 00:52:26 +00:00
return p_profile - > general - > prefCalcMax ( ) ? percentile ( code , 0.995f ) : Max ( code ) ;
2014-08-11 18:29:44 +00:00
}
EventDataType Day : : calcPercentile ( ChannelID code )
{
double p = p_profile - > general - > prefCalcPercentile ( ) / 100.0 ;
return percentile ( code , p ) ;
}
QString Day : : calcMiddleLabel ( ChannelID code )
{
int c = p_profile - > general - > prefCalcMiddle ( ) ;
if ( c = = 0 ) {
2014-08-17 12:56:05 +00:00
return QObject : : tr ( " %1 %2 " ) . arg ( STR_TR_Median ) . arg ( schema : : channel [ code ] . label ( ) ) ;
2014-08-11 18:29:44 +00:00
} else if ( c = = 1 ) {
2017-09-21 14:50:18 +00:00
return QObject : : tr ( " %1 %2 " ) . arg ( STR_TR_WAvg ) . arg ( schema : : channel [ code ] . label ( ) ) ;
2014-08-11 18:29:44 +00:00
} else {
2017-09-21 14:50:18 +00:00
return QObject : : tr ( " %1 %2 " ) . arg ( STR_TR_Avg ) . arg ( schema : : channel [ code ] . label ( ) ) ;
2014-08-11 18:29:44 +00:00
}
}
QString Day : : calcMaxLabel ( ChannelID code )
{
2014-08-17 12:56:05 +00:00
return QObject : : tr ( " %1 %2 " ) . arg ( p_profile - > general - > prefCalcMax ( ) ? QObject : : tr ( " Peak " ) : STR_TR_Max ) . arg ( schema : : channel [ code ] . label ( ) ) ;
2014-08-11 18:29:44 +00:00
}
QString Day : : calcPercentileLabel ( ChannelID code )
{
2014-08-17 12:56:05 +00:00
return QObject : : tr ( " %1% %2 " ) . arg ( p_profile - > general - > prefCalcPercentile ( ) , 0 , ' f ' , 0 ) . arg ( schema : : channel [ code ] . label ( ) ) ;
2014-08-11 18:29:44 +00:00
}
2014-07-30 17:14:28 +00:00
EventDataType Day : : countInsideSpan ( ChannelID span , ChannelID code )
{
int count = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
count + = sess - > countInsideSpan ( span , code ) ;
2014-07-30 17:14:28 +00:00
}
}
return count ;
}
2014-08-06 07:28:24 +00:00
EventDataType Day : : lookupValue ( ChannelID code , qint64 time , bool square )
2014-07-20 16:22:51 +00:00
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
if ( ( time > sess - > first ( ) ) & & ( time < sess - > last ( ) ) ) {
if ( sess - > channelExists ( code ) ) {
return sess - > SearchValue ( code , time , square ) ;
2014-08-22 13:59:27 +00:00
}
2014-07-20 16:22:51 +00:00
}
}
}
return 0 ;
}
2014-05-15 20:48:05 +00:00
EventDataType Day : : timeAboveThreshold ( ChannelID code , EventDataType threshold )
{
EventDataType val = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_availableChannels . contains ( code ) ) {
val + = sess - > timeAboveThreshold ( code , threshold ) ;
2014-05-15 20:48:05 +00:00
}
}
return val ;
}
EventDataType Day : : timeBelowThreshold ( ChannelID code , EventDataType threshold )
{
EventDataType val = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
val + = sess - > timeBelowThreshold ( code , threshold ) ;
2014-05-15 20:48:05 +00:00
}
}
return val ;
}
2011-07-31 20:24:43 +00:00
EventDataType Day : : settings_sum ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
EventDataType val = 0 ;
2011-12-28 12:03:48 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
auto set = sess - > settings . find ( code ) ;
if ( set ! = sess - > settings . end ( ) ) {
2014-04-23 06:00:09 +00:00
val + = set . value ( ) . toDouble ( ) ;
}
2011-06-26 08:30:44 +00:00
}
}
return val ;
}
2011-07-31 20:24:43 +00:00
EventDataType Day : : settings_max ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-07-06 00:22:50 +00:00
EventDataType min = - std : : numeric_limits < EventDataType > : : max ( ) ;
2014-04-22 05:28:58 +00:00
EventDataType max = min ;
EventDataType value ;
2014-04-17 05:58:57 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
value = sess - > settings . value ( code , min ) . toFloat ( ) ;
2014-04-22 05:28:58 +00:00
if ( value > max ) {
max = value ;
}
2011-06-26 08:30:44 +00:00
}
}
2014-04-22 05:28:58 +00:00
return max ;
2011-06-26 08:30:44 +00:00
}
2014-04-22 05:28:58 +00:00
2011-07-31 20:24:43 +00:00
EventDataType Day : : settings_min ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-22 05:28:58 +00:00
EventDataType max = std : : numeric_limits < EventDataType > : : max ( ) ;
EventDataType min = max ;
EventDataType value ;
2014-04-17 05:58:57 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
value = sess - > settings . value ( code , max ) . toFloat ( ) ;
2014-04-22 05:28:58 +00:00
if ( value < min ) {
min = value ;
2011-06-26 08:30:44 +00:00
}
}
}
2014-04-22 05:28:58 +00:00
return min ;
2011-06-26 08:30:44 +00:00
}
2011-07-31 20:24:43 +00:00
EventDataType Day : : settings_avg ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
EventDataType val = 0 ;
int cnt = 0 ;
2011-12-28 12:03:48 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
auto set = sess - > settings . find ( code ) ;
2014-04-22 05:28:58 +00:00
2018-05-05 21:58:11 +00:00
if ( set ! = sess - > settings . end ( ) ) {
2014-04-22 05:28:58 +00:00
val + = set . value ( ) . toDouble ( ) ;
cnt + + ;
}
2011-06-26 08:30:44 +00:00
}
}
2014-10-08 16:51:09 +00:00
val = ( cnt > 0 ) ? ( val / EventDataType ( cnt ) ) : val ;
2014-04-22 05:28:58 +00:00
2011-06-26 08:30:44 +00:00
return val ;
}
2014-04-22 05:28:58 +00:00
2011-07-31 20:24:43 +00:00
EventDataType Day : : settings_wavg ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
double s0 = 0 , s1 = 0 , s2 = 0 , tmp ;
2011-12-28 12:03:48 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
auto set = sess - > settings . find ( code ) ;
2014-04-17 05:58:57 +00:00
2018-05-05 21:58:11 +00:00
if ( set ! = sess - > settings . end ( ) ) {
s0 = sess - > hours ( ) ;
2014-04-22 05:28:58 +00:00
tmp = set . value ( ) . toDouble ( ) ;
s1 + = tmp * s0 ;
s2 + = s0 ;
}
2011-06-26 08:30:44 +00:00
}
}
2014-04-17 05:58:57 +00:00
if ( s2 = = 0 ) { return 0 ; }
tmp = ( s1 / s2 ) ;
2011-12-26 18:26:06 +00:00
return tmp ;
2011-06-26 08:30:44 +00:00
}
2012-01-01 15:47:21 +00:00
2014-04-17 05:58:57 +00:00
EventDataType Day : : percentile ( ChannelID code , EventDataType percentile )
2011-12-11 09:45:28 +00:00
{
2014-04-23 06:00:09 +00:00
// Cache this calculation?
2014-04-17 05:58:57 +00:00
// QHash<ChannelID, QHash<EventDataType, EventDataType> >::iterator pi;
// pi=perc_cache.find(code);
// if (pi!=perc_cache.end()) {
// QHash<EventDataType, EventDataType> & hsh=pi.value();
// QHash<EventDataType, EventDataType>::iterator hi=hsh.find(
// if (hi!=pi.value().end()) {
// return hi.value();
// }
// }
2011-12-11 09:45:28 +00:00
2014-04-22 05:28:58 +00:00
QHash < EventStoreType , qint64 > wmap ; // weight map
2012-01-05 04:37:22 +00:00
2014-05-17 05:04:40 +00:00
QHash < EventStoreType , qint64 > : : iterator wmapit ;
2014-04-17 05:58:57 +00:00
qint64 SN = 0 ;
2012-01-05 04:37:22 +00:00
2014-04-17 05:58:57 +00:00
EventDataType lastgain = 0 , gain = 0 ;
2012-01-05 04:37:22 +00:00
// First Calculate count of all events
2012-02-01 14:53:31 +00:00
bool timeweight ;
2012-02-02 03:48:44 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( ! sess - > enabled ( ) ) { continue ; }
2011-12-28 12:03:48 +00:00
2018-05-05 21:58:11 +00:00
auto ei = sess - > m_valuesummary . find ( code ) ;
if ( ei = = sess - > m_valuesummary . end ( ) ) { continue ; }
2012-01-05 04:37:22 +00:00
2018-05-05 21:58:11 +00:00
auto tei = sess - > m_timesummary . find ( code ) ;
timeweight = ( tei ! = sess - > m_timesummary . end ( ) ) ;
gain = sess - > m_gain [ code ] ;
2012-01-05 12:12:42 +00:00
// Here's assuming gains don't change accross a days sessions
// Can't assume this in any multi day calculations..
2014-04-17 05:58:57 +00:00
if ( lastgain > 0 ) {
if ( gain ! = lastgain ) {
2012-01-09 08:05:20 +00:00
qDebug ( ) < < " Gains differ across sessions: " < < gain < < lastgain ;
2012-01-05 12:12:42 +00:00
}
}
2014-04-17 05:58:57 +00:00
lastgain = gain ;
2012-01-05 12:12:42 +00:00
2012-02-01 14:53:31 +00:00
qint64 weight ;
2014-04-17 05:58:57 +00:00
2013-01-17 18:26:11 +00:00
//qint64 tval;
2012-02-01 14:53:31 +00:00
if ( timeweight ) {
2014-05-17 05:04:40 +00:00
wmap . reserve ( wmap . size ( ) + tei . value ( ) . size ( ) ) ;
2018-05-05 21:58:11 +00:00
for ( auto it = tei . value ( ) . begin ( ) , teival_end = tei . value ( ) . end ( ) ; it ! = teival_end ; + + it ) {
2014-04-23 06:00:09 +00:00
weight = it . value ( ) ;
2014-04-17 05:58:57 +00:00
SN + = weight ;
2014-05-17 05:04:40 +00:00
wmap [ it . key ( ) ] + = weight ;
2012-02-01 14:53:31 +00:00
}
} else {
2014-05-17 05:04:40 +00:00
wmap . reserve ( wmap . size ( ) + ei . value ( ) . size ( ) ) ;
2018-05-05 21:58:11 +00:00
for ( auto it = ei . value ( ) . begin ( ) , eival_end = ei . value ( ) . end ( ) ; it ! = eival_end ; + + it ) {
2014-04-23 06:00:09 +00:00
weight = it . value ( ) ;
2012-02-01 14:53:31 +00:00
2014-04-17 05:58:57 +00:00
SN + = weight ;
2012-02-01 14:53:31 +00:00
2014-05-17 05:04:40 +00:00
wmap [ it . key ( ) ] + = weight ;
2012-02-01 14:53:31 +00:00
}
2011-12-11 09:45:28 +00:00
}
}
2012-01-01 15:47:21 +00:00
2012-01-05 04:37:22 +00:00
QVector < ValueCount > valcnt ;
2014-05-17 05:04:40 +00:00
valcnt . resize ( wmap . size ( ) ) ;
2012-01-05 04:37:22 +00:00
// Build sorted list of value/counts
2014-04-22 05:28:58 +00:00
2018-05-05 21:58:11 +00:00
auto wmap_end = wmap . end ( ) ;
2014-05-17 05:04:40 +00:00
int ii = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto it = wmap . begin ( ) ; it ! = wmap_end ; + + it ) {
2014-05-17 05:04:40 +00:00
valcnt [ ii + + ] = ValueCount ( EventDataType ( it . key ( ) ) * gain , it . value ( ) , 0 ) ;
2012-01-05 04:37:22 +00:00
}
2014-04-17 05:58:57 +00:00
2012-01-05 04:37:22 +00:00
// sort by weight, then value
2018-06-12 16:51:58 +00:00
//qSort(valcnt);
std : : sort ( valcnt . begin ( ) , valcnt . end ( ) ) ;
2012-01-05 04:37:22 +00:00
//double SN=100.0/double(N); // 100% / overall sum
2014-04-17 05:58:57 +00:00
double p = 100.0 * percentile ;
2012-01-05 04:37:22 +00:00
2014-04-17 05:58:57 +00:00
double nth = double ( SN ) * percentile ; // index of the position in the unweighted set would be
double nthi = floor ( nth ) ;
2012-01-05 04:37:22 +00:00
2014-04-17 05:58:57 +00:00
qint64 sum1 = 0 , sum2 = 0 ;
qint64 w1 , w2 = 0 ;
double v1 = 0 , v2 ;
2012-01-05 04:37:22 +00:00
2014-04-17 05:58:57 +00:00
int N = valcnt . size ( ) ;
int k = 0 ;
2012-01-05 04:37:22 +00:00
2014-04-17 05:58:57 +00:00
for ( k = 0 ; k < N ; k + + ) {
2014-05-17 05:04:40 +00:00
v1 = valcnt . at ( k ) . value ;
w1 = valcnt . at ( k ) . count ;
2014-04-17 05:58:57 +00:00
sum1 + = w1 ;
2012-01-05 04:37:22 +00:00
if ( sum1 > nthi ) {
return v1 ;
}
2014-04-17 05:58:57 +00:00
if ( sum1 = = nthi ) {
2012-01-05 04:37:22 +00:00
break ; // boundary condition
}
}
2014-04-17 05:58:57 +00:00
if ( k > = N ) {
2012-01-05 04:37:22 +00:00
return v1 ;
2014-04-17 05:58:57 +00:00
}
2012-01-05 04:37:22 +00:00
2014-09-11 14:23:08 +00:00
if ( valcnt . size ( ) = = 1 ) {
return valcnt [ 0 ] . value ;
}
2014-04-17 05:58:57 +00:00
v2 = valcnt [ k + 1 ] . value ;
w2 = valcnt [ k + 1 ] . count ;
sum2 = sum1 + w2 ;
2012-01-05 04:37:22 +00:00
// value lies between v1 and v2
2014-04-17 05:58:57 +00:00
double px = 100.0 / double ( SN ) ; // Percentile represented by one full value
2012-01-05 04:37:22 +00:00
// calculate percentile ranks
2014-04-17 05:58:57 +00:00
double p1 = px * ( double ( sum1 ) - ( double ( w1 ) / 2.0 ) ) ;
double p2 = px * ( double ( sum2 ) - ( double ( w2 ) / 2.0 ) ) ;
2012-01-05 04:37:22 +00:00
// calculate linear interpolation
2014-04-17 05:58:57 +00:00
double v = v1 + ( ( p - p1 ) / ( p2 - p1 ) ) * ( v2 - v1 ) ;
2012-01-05 04:37:22 +00:00
return v ;
2014-04-17 05:58:57 +00:00
// p1.....p.............p2
// 37 55 70
2011-12-11 09:45:28 +00:00
}
2011-12-24 01:22:41 +00:00
EventDataType Day : : p90 ( ChannelID code )
2011-07-31 20:24:43 +00:00
{
2014-05-08 04:46:23 +00:00
return percentile ( code , 0.90F ) ;
2011-07-31 20:24:43 +00:00
}
2011-06-26 08:30:44 +00:00
2014-09-01 04:49:05 +00:00
EventDataType Day : : rangeCount ( ChannelID code , qint64 st , qint64 et )
{
int cnt = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
cnt + = sess - > rangeCount ( code , st , et ) ;
2014-09-01 04:49:05 +00:00
}
}
return cnt ;
}
EventDataType Day : : rangeSum ( ChannelID code , qint64 st , qint64 et )
{
double val = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
val + = sess - > rangeSum ( code , st , et ) ;
2014-09-01 04:49:05 +00:00
}
}
return val ;
}
EventDataType Day : : rangeAvg ( ChannelID code , qint64 st , qint64 et )
{
double val = 0 ;
int cnt = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
val + = sess - > rangeSum ( code , st , et ) ;
cnt + = sess - > rangeCount ( code , st , et ) ;
2014-09-01 04:49:05 +00:00
}
}
if ( cnt = = 0 ) { return 0 ; }
val / = double ( cnt ) ;
return val ;
}
EventDataType Day : : rangeWavg ( ChannelID code , qint64 st , qint64 et )
{
double sum = 0 ;
double cnt = 0 ;
2018-05-05 21:58:11 +00:00
qint64 lasttime , time ;
double data , duration ;
for ( auto & sess : sessions ) {
auto EVEC = sess - > eventlist . find ( code ) ;
if ( EVEC = = sess - > eventlist . end ( ) ) continue ;
for ( auto & el : EVEC . value ( ) ) {
2014-09-01 04:49:05 +00:00
if ( el - > count ( ) < 1 ) continue ;
2018-05-05 21:58:11 +00:00
lasttime = el - > time ( 0 ) ;
2014-09-01 04:49:05 +00:00
if ( lasttime < st )
lasttime = st ;
for ( unsigned i = 1 ; i < el - > count ( ) ; i + + ) {
2018-05-05 21:58:11 +00:00
data = el - > data ( i ) ;
time = el - > time ( i ) ;
2014-09-01 04:49:05 +00:00
if ( time < st ) {
lasttime = st ;
continue ;
}
if ( time > et ) {
time = et ;
}
2018-05-05 21:58:11 +00:00
duration = double ( time - lasttime ) / 1000.0 ;
2014-09-01 04:49:05 +00:00
sum + = data * duration ;
cnt + = duration ;
if ( time > = et ) break ;
lasttime = time ;
}
}
}
if ( cnt < 0.000001 )
return 0 ;
return sum / cnt ;
}
// Boring non weighted percentile
EventDataType Day : : rangePercentile ( ChannelID code , float p , qint64 st , qint64 et )
{
int count = rangeCount ( code , st , et ) ;
QVector < EventDataType > list ;
list . resize ( count ) ;
int idx = 0 ;
2018-05-05 21:58:11 +00:00
qint64 time ;
2014-09-01 04:49:05 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
auto EVEC = sess - > eventlist . find ( code ) ;
if ( EVEC = = sess - > eventlist . end ( ) ) continue ;
2014-09-01 04:49:05 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & el : EVEC . value ( ) ) {
2014-09-01 04:49:05 +00:00
for ( unsigned i = 0 ; i < el - > count ( ) ; i + + ) {
2018-05-05 21:58:11 +00:00
time = el - > time ( i ) ;
2014-09-01 04:49:05 +00:00
if ( ( time < st ) | | ( time > et ) ) continue ;
list [ idx + + ] = el - > data ( i ) ;
}
}
}
// TODO: use nth_element instead..
2018-06-12 16:51:58 +00:00
//qSort(list);
std : : sort ( list . begin ( ) , list . end ( ) ) ;
2014-09-01 04:49:05 +00:00
float b = float ( idx ) * p ;
int a = floor ( b ) ;
int c = ceil ( b ) ;
if ( ( a = = c ) | | ( c > = idx ) ) {
return list [ a ] ;
}
EventDataType v1 = list [ a ] ;
EventDataType v2 = list [ c ] ;
EventDataType diff = v2 - v1 ; // the whole == C-A
double ba = b - float ( a ) ; // A....B...........C == B-A
double val = v1 + diff * ba ;
return val ;
}
2011-07-31 20:24:43 +00:00
EventDataType Day : : avg ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
double val = 0 ;
2011-06-26 08:30:44 +00:00
// Cache this?
2014-04-17 05:58:57 +00:00
int cnt = 0 ;
2011-06-26 08:30:44 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
val + = sess - > sum ( code ) ;
cnt + = sess - > count ( code ) ;
2011-06-26 08:30:44 +00:00
}
}
2014-04-17 05:58:57 +00:00
if ( cnt = = 0 ) { return 0 ; }
2014-09-01 04:49:05 +00:00
val / = double ( cnt ) ;
2014-04-17 05:58:57 +00:00
2014-09-01 04:49:05 +00:00
return val ;
2011-06-26 08:30:44 +00:00
}
2011-07-31 20:24:43 +00:00
EventDataType Day : : sum ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
// Cache this?
2014-04-17 05:58:57 +00:00
EventDataType val = 0 ;
2011-06-26 08:30:44 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_sum . contains ( code ) ) {
val + = sess - > sum ( code ) ;
2011-06-26 08:30:44 +00:00
}
}
2014-04-17 05:58:57 +00:00
2011-06-26 08:30:44 +00:00
return val ;
}
2011-07-31 20:24:43 +00:00
EventDataType Day : : wavg ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
double s0 = 0 , s1 = 0 , s2 = 0 ;
2011-08-07 11:37:56 +00:00
qint64 d ;
2011-12-28 12:03:48 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_wavg . contains ( code ) ) {
d = sess - > length ( ) ;
2014-04-17 05:58:57 +00:00
s0 = double ( d ) / 3600000.0 ;
if ( s0 > 0 ) {
2018-05-05 21:58:11 +00:00
s1 + = sess - > wavg ( code ) * s0 ;
2014-04-17 05:58:57 +00:00
s2 + = s0 ;
2011-08-07 11:37:56 +00:00
}
2011-06-26 08:30:44 +00:00
}
}
2014-04-17 05:58:57 +00:00
if ( s2 = = 0 ) {
2011-08-07 11:37:56 +00:00
return 0 ;
2014-04-17 05:58:57 +00:00
}
2011-08-07 11:37:56 +00:00
2014-04-17 05:58:57 +00:00
return ( s1 / s2 ) ;
2011-06-26 08:30:44 +00:00
}
2014-04-22 05:28:58 +00:00
2011-07-03 02:43:50 +00:00
// Total session time in milliseconds
2011-07-02 14:35:50 +00:00
qint64 Day : : total_time ( )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
qint64 d_totaltime = 0 ;
QMultiMap < qint64 , bool > range ;
2012-01-24 15:51:11 +00:00
//range.reserve(size()*2);
2014-04-23 06:00:09 +00:00
// Remember sessions may overlap..
2011-12-28 12:03:48 +00:00
2014-05-07 00:10:13 +00:00
qint64 first , last ;
2014-04-22 05:28:58 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
int slicesize = sess - > m_slices . size ( ) ;
if ( sess - > enabled ( ) & & ( sess - > type ( ) ! = MT_JOURNAL ) ) {
first = sess - > first ( ) ;
last = sess - > last ( ) ;
2014-08-20 17:17:13 +00:00
2014-09-18 14:31:31 +00:00
if ( slicesize = = 0 ) {
// This algorithm relies on non zero length, and correctly ordered sessions
if ( last > first ) {
range . insert ( first , 0 ) ;
range . insert ( last , 1 ) ;
2018-05-05 21:58:11 +00:00
d_totaltime + = sess - > length ( ) ;
2019-06-10 19:02:54 +00:00
if ( sess - > length ( ) = = 0 ) {
qWarning ( ) < < sess - > s_session < < " 0 length session " ;
}
2014-09-18 14:31:31 +00:00
}
} else {
2018-05-05 21:58:11 +00:00
for ( auto & slice : sess - > m_slices ) {
2019-06-04 00:12:17 +00:00
if ( slice . status = = MaskOn ) {
2014-09-18 14:31:31 +00:00
range . insert ( slice . start , 0 ) ;
range . insert ( slice . end , 1 ) ;
d_totaltime + = slice . end - slice . start ;
2019-06-10 19:02:54 +00:00
if ( slice . end - slice . start = = 0 ) {
qWarning ( ) < < sess - > s_session < < " 0 length slice " ;
}
2014-09-18 14:31:31 +00:00
}
}
2014-08-20 17:17:13 +00:00
}
}
}
bool b ;
int nest = 0 ;
qint64 ti = 0 ;
qint64 total = 0 ;
// This is my implementation of a typical "brace counting" algorithm mentioned here:
// http://stackoverflow.com/questions/7468948/problem-calculating-overlapping-date-ranges
2018-05-05 21:58:11 +00:00
auto rend = range . end ( ) ;
for ( auto rit = range . begin ( ) ; rit ! = rend ; + + rit ) {
2014-08-20 17:17:13 +00:00
b = rit . value ( ) ;
if ( ! b ) {
if ( ! ti ) {
ti = rit . key ( ) ;
}
nest + + ;
} else {
if ( - - nest < = 0 ) {
total + = rit . key ( ) - ti ;
ti = 0 ;
}
}
}
if ( total ! = d_totaltime ) {
// They can overlap.. tough.
// qDebug() << "Sessions Times overlaps!" << total << d_totaltime;
}
return total ; //d_totaltime;
}
// Total session time in milliseconds, only considering machinetype
qint64 Day : : total_time ( MachineType type )
{
qint64 d_totaltime = 0 ;
QMultiMap < qint64 , bool > range ;
//range.reserve(size()*2);
// Remember sessions may overlap..
qint64 first , last ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
int slicesize = sess - > m_slices . size ( ) ;
2014-08-20 17:17:13 +00:00
2018-05-05 21:58:11 +00:00
if ( sess - > enabled ( ) & & ( sess - > type ( ) = = type ) ) {
first = sess - > first ( ) ;
last = sess - > last ( ) ;
2014-05-07 00:10:13 +00:00
// This algorithm relies on non zero length, and correctly ordered sessions
2014-09-18 14:31:31 +00:00
if ( slicesize = = 0 ) {
if ( last > first ) {
range . insert ( first , 0 ) ;
range . insert ( last , 1 ) ;
2018-05-05 21:58:11 +00:00
d_totaltime + = sess - > length ( ) ;
2019-06-10 19:02:54 +00:00
if ( sess - > length ( ) = = 0 ) {
qWarning ( ) < < sess - > s_session < < " 0 length session " ;
}
2014-09-18 14:31:31 +00:00
}
} else {
2018-05-05 21:58:11 +00:00
for ( const auto & slice : sess - > m_slices ) {
2019-06-04 00:12:17 +00:00
if ( slice . status = = MaskOn ) {
2014-09-18 14:31:31 +00:00
range . insert ( slice . start , 0 ) ;
range . insert ( slice . end , 1 ) ;
d_totaltime + = slice . end - slice . start ;
2019-06-10 19:02:54 +00:00
if ( slice . end - slice . start = = 0 ) {
qWarning ( ) < < sess - > s_session < < " 0 length slice " ;
}
2014-09-18 14:31:31 +00:00
}
}
2014-05-07 00:10:13 +00:00
}
2014-04-22 05:28:58 +00:00
}
2011-06-26 08:30:44 +00:00
}
2012-01-24 15:51:11 +00:00
bool b ;
2014-04-17 05:58:57 +00:00
int nest = 0 ;
2014-05-07 00:10:13 +00:00
qint64 ti = 0 ;
2014-04-17 05:58:57 +00:00
qint64 total = 0 ;
2012-01-24 16:45:18 +00:00
// This is my implementation of a typical "brace counting" algorithm mentioned here:
// http://stackoverflow.com/questions/7468948/problem-calculating-overlapping-date-ranges
2014-04-22 05:28:58 +00:00
2018-05-05 21:58:11 +00:00
auto rend = range . end ( ) ;
for ( auto rit = range . begin ( ) ; rit ! = rend ; + + rit ) {
2014-04-22 05:28:58 +00:00
b = rit . value ( ) ;
2014-04-17 05:58:57 +00:00
2012-01-24 15:51:11 +00:00
if ( ! b ) {
2014-04-22 05:28:58 +00:00
if ( ! ti ) {
ti = rit . key ( ) ;
}
2014-04-17 05:58:57 +00:00
2012-01-24 15:51:11 +00:00
nest + + ;
} else {
if ( - - nest < = 0 ) {
2014-04-22 05:28:58 +00:00
total + = rit . key ( ) - ti ;
2014-04-17 05:58:57 +00:00
ti = 0 ;
2012-01-24 15:51:11 +00:00
}
}
}
2014-04-17 05:58:57 +00:00
if ( total ! = d_totaltime ) {
2014-05-04 18:23:38 +00:00
// They can overlap.. tough.
// qDebug() << "Sessions Times overlaps!" << total << d_totaltime;
2012-01-24 15:51:11 +00:00
}
2014-04-17 05:58:57 +00:00
2012-01-24 15:51:11 +00:00
return total ; //d_totaltime;
2011-06-26 08:30:44 +00:00
}
2014-04-22 05:28:58 +00:00
2014-08-20 17:17:13 +00:00
2011-12-28 14:03:09 +00:00
bool Day : : hasEnabledSessions ( )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
2014-04-22 05:28:58 +00:00
return true ;
2011-12-28 14:03:09 +00:00
}
}
2014-04-22 05:28:58 +00:00
return false ;
2011-12-28 14:03:09 +00:00
}
2014-08-20 17:17:13 +00:00
bool Day : : hasEnabledSessions ( MachineType type )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( ( sess - > type ( ) = = type ) & & sess - > enabled ( ) ) {
2014-08-20 17:17:13 +00:00
return true ;
}
}
return false ;
}
2011-12-11 09:45:28 +00:00
/*EventDataType Day::percentile(ChannelID code,double percent)
2011-06-26 08:30:44 +00:00
{
double val = 0 ;
int cnt = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > eventlist . find ( code ) ! = sess - > eventlist . end ( ) ) {
val + = sess - > percentile ( code , percent ) ;
2011-06-26 08:30:44 +00:00
cnt + + ;
}
}
if ( cnt = = 0 ) return 0 ;
return EventDataType ( val / cnt ) ;
2011-12-11 09:45:28 +00:00
} */
2011-06-26 08:30:44 +00:00
2011-07-31 20:24:43 +00:00
qint64 Day : : first ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
qint64 date = 0 ;
2011-07-02 14:35:50 +00:00
qint64 tmp ;
2011-06-26 08:30:44 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
tmp = sess - > first ( code ) ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
if ( ! tmp ) { continue ; }
if ( ! date ) {
date = tmp ;
} else {
if ( tmp < date ) { date = tmp ; }
}
2011-06-26 08:30:44 +00:00
}
}
2014-04-17 05:58:57 +00:00
2011-06-26 08:30:44 +00:00
return date ;
}
2011-07-31 20:24:43 +00:00
qint64 Day : : last ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
qint64 date = 0 ;
2011-07-02 14:35:50 +00:00
qint64 tmp ;
2011-06-26 08:30:44 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
tmp = sess - > last ( code ) ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
if ( ! tmp ) { continue ; }
if ( ! date ) {
date = tmp ;
} else {
if ( tmp > date ) { date = tmp ; }
}
2011-06-26 08:30:44 +00:00
}
}
2014-04-17 05:58:57 +00:00
2011-06-26 08:30:44 +00:00
return date ;
}
2013-10-25 10:39:30 +00:00
2011-12-17 14:38:15 +00:00
EventDataType Day : : Min ( ChannelID code )
2011-06-26 08:30:44 +00:00
{
2014-04-17 05:58:57 +00:00
EventDataType min = 0 ;
2011-07-27 09:21:53 +00:00
EventDataType tmp ;
2014-04-17 05:58:57 +00:00
bool first = true ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_min . contains ( code ) ) {
2014-04-22 05:28:58 +00:00
2018-05-05 21:58:11 +00:00
tmp = sess - > Min ( code ) ;
2014-04-22 05:28:58 +00:00
if ( first ) {
min = tmp ;
first = false ;
} else {
if ( tmp < min ) { min = tmp ; }
}
2011-07-27 09:21:53 +00:00
}
2011-06-26 08:30:44 +00:00
}
2014-04-17 05:58:57 +00:00
2011-07-27 09:21:53 +00:00
return min ;
}
2011-06-26 08:30:44 +00:00
2013-10-25 10:39:30 +00:00
EventDataType Day : : physMin ( ChannelID code )
{
2014-04-17 05:58:57 +00:00
EventDataType min = 0 ;
2013-10-25 10:39:30 +00:00
EventDataType tmp ;
2014-04-17 05:58:57 +00:00
bool first = true ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_min . contains ( code ) ) {
2013-10-25 10:39:30 +00:00
2018-05-05 21:58:11 +00:00
tmp = sess - > physMin ( code ) ;
2014-04-22 05:28:58 +00:00
if ( first ) {
min = tmp ;
first = false ;
} else {
if ( tmp < min ) { min = tmp ; }
}
2013-10-25 10:39:30 +00:00
}
}
2014-04-17 05:58:57 +00:00
2013-10-25 10:39:30 +00:00
return min ;
}
2011-12-10 12:14:48 +00:00
bool Day : : hasData ( ChannelID code , SummaryType type )
{
2014-04-17 05:58:57 +00:00
bool has = false ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > type ( ) = = MT_JOURNAL ) continue ;
2014-04-17 05:58:57 +00:00
2018-05-05 21:58:11 +00:00
if ( sess - > enabled ( ) ) {
2014-04-22 05:28:58 +00:00
switch ( type ) {
// case ST_90P:
// has=sess->m_90p.contains(code);
// break;
case ST_PERC :
2018-05-05 21:58:11 +00:00
has = sess - > m_valuesummary . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_MIN :
2018-05-05 21:58:11 +00:00
has = sess - > m_min . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_MAX :
2018-05-05 21:58:11 +00:00
has = sess - > m_max . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_CNT :
2018-05-05 21:58:11 +00:00
has = sess - > m_cnt . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_AVG :
2018-05-05 21:58:11 +00:00
has = sess - > m_avg . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_WAVG :
2018-05-05 21:58:11 +00:00
has = sess - > m_wavg . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_CPH :
2018-05-05 21:58:11 +00:00
has = sess - > m_cph . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_SPH :
2018-05-05 21:58:11 +00:00
has = sess - > m_sph . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_FIRST :
2018-05-05 21:58:11 +00:00
has = sess - > m_firstchan . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_LAST :
2018-05-05 21:58:11 +00:00
has = sess - > m_lastchan . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
case ST_SUM :
2018-05-05 21:58:11 +00:00
has = sess - > m_sum . contains ( code ) ;
2014-04-22 05:28:58 +00:00
break ;
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
default :
break ;
}
2011-12-10 12:14:48 +00:00
2014-04-22 05:28:58 +00:00
if ( has ) { break ; }
}
2011-12-10 12:14:48 +00:00
}
2014-04-17 05:58:57 +00:00
2011-12-10 12:14:48 +00:00
return has ;
}
2011-12-17 14:38:15 +00:00
EventDataType Day : : Max ( ChannelID code )
2011-07-27 09:21:53 +00:00
{
2014-04-17 05:58:57 +00:00
EventDataType max = 0 ;
2011-07-27 09:21:53 +00:00
EventDataType tmp ;
2014-04-17 05:58:57 +00:00
bool first = true ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_max . contains ( code ) ) {
2011-12-28 12:03:48 +00:00
2018-05-05 21:58:11 +00:00
tmp = sess - > Max ( code ) ;
2014-04-22 05:28:58 +00:00
if ( first ) {
max = tmp ;
first = false ;
} else {
if ( tmp > max ) { max = tmp ; }
}
2011-07-27 09:21:53 +00:00
}
}
return max ;
2011-06-26 08:30:44 +00:00
}
2013-10-25 10:39:30 +00:00
EventDataType Day : : physMax ( ChannelID code )
{
2014-04-17 05:58:57 +00:00
EventDataType max = 0 ;
2013-10-25 10:39:30 +00:00
EventDataType tmp ;
2014-04-17 05:58:57 +00:00
bool first = true ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_max . contains ( code ) ) {
tmp = sess - > physMax ( code ) ;
2013-10-25 10:39:30 +00:00
2014-04-22 05:28:58 +00:00
if ( first ) {
max = tmp ;
first = false ;
} else {
if ( tmp > max ) { max = tmp ; }
}
2013-10-25 10:39:30 +00:00
}
}
return max ;
}
2011-09-10 15:43:40 +00:00
EventDataType Day : : cph ( ChannelID code )
{
2014-04-17 05:58:57 +00:00
double sum = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_cnt . contains ( code ) ) {
sum + = sess - > count ( code ) ;
2014-04-22 05:28:58 +00:00
}
2011-09-10 15:43:40 +00:00
}
2014-04-17 05:58:57 +00:00
sum / = hours ( ) ;
2011-09-10 15:43:40 +00:00
return sum ;
}
EventDataType Day : : sph ( ChannelID code )
{
2014-04-17 05:58:57 +00:00
EventDataType sum = 0 ;
EventDataType h = 0 ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_sum . contains ( code ) ) {
sum + = sess - > sum ( code ) / 3600.0 ;
2014-04-22 05:28:58 +00:00
}
2011-09-10 15:43:40 +00:00
}
2014-04-17 05:58:57 +00:00
h = hours ( ) ;
sum = ( 100.0 / h ) * sum ;
2011-09-10 15:43:40 +00:00
return sum ;
}
2014-06-20 02:06:57 +00:00
EventDataType Day : : count ( ChannelID code )
2011-07-27 09:21:53 +00:00
{
2014-06-20 02:06:57 +00:00
EventDataType total = 0 ;
2014-04-17 05:58:57 +00:00
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > m_cnt . contains ( code ) ) {
total + = sess - > count ( code ) ;
2014-04-22 05:28:58 +00:00
}
2011-07-27 09:21:53 +00:00
}
2014-06-20 02:06:57 +00:00
return total ;
2011-07-27 09:21:53 +00:00
}
2014-04-22 05:28:58 +00:00
2018-05-06 16:59:50 +00:00
bool Day : : noSettings ( Machine * mach )
{
for ( auto & sess : sessions ) {
if ( ( mach = = nullptr ) & & sess - > noSettings ( ) ) {
// If this day generally has just summary data.
return true ;
} else if ( ( mach = = sess - > machine ( ) ) & & sess - > noSettings ( ) ) {
// Focus only on machine mach
return true ;
}
}
return false ;
}
2018-04-28 05:33:26 +00:00
bool Day : : summaryOnly ( Machine * mach )
2014-05-19 03:46:02 +00:00
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( ( mach = = nullptr ) & & sess - > summaryOnly ( ) ) {
2018-04-28 05:33:26 +00:00
// If this day generally has just summary data.
2014-07-02 11:58:36 +00:00
return true ;
2018-05-05 21:58:11 +00:00
} else if ( ( mach = = sess - > machine ( ) ) & & sess - > summaryOnly ( ) ) {
2018-04-28 05:33:26 +00:00
// Focus only on machine mach
return true ;
}
2014-05-19 03:46:02 +00:00
}
return false ;
}
2011-09-18 15:43:14 +00:00
bool Day : : settingExists ( ChannelID id )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
auto set = sess - > settings . find ( id ) ;
if ( set ! = sess - > settings . end ( ) ) {
2014-04-22 05:28:58 +00:00
return true ;
}
2011-09-18 15:43:14 +00:00
}
}
return false ;
}
2014-04-22 05:28:58 +00:00
2011-12-23 10:52:31 +00:00
bool Day : : eventsLoaded ( )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > eventsLoaded ( ) ) {
2014-04-22 05:28:58 +00:00
return true ;
2011-12-23 10:52:31 +00:00
}
}
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
return false ;
2011-12-23 10:52:31 +00:00
}
2011-08-07 11:37:56 +00:00
bool Day : : channelExists ( ChannelID id )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) & & sess - > eventlist . contains ( id ) ) {
2014-04-22 05:28:58 +00:00
return true ;
2011-12-10 12:14:48 +00:00
}
}
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
return false ;
2011-09-17 12:39:00 +00:00
}
2014-08-17 15:36:53 +00:00
bool Day : : hasEvents ( ) {
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > eventlist . size ( ) > 0 ) return true ;
2014-08-17 15:36:53 +00:00
}
return false ;
}
2014-04-22 05:28:58 +00:00
2011-09-17 12:39:00 +00:00
bool Day : : channelHasData ( ChannelID id )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > enabled ( ) ) {
if ( sess - > m_cnt . contains ( id ) ) {
2014-04-22 05:28:58 +00:00
return true ;
}
2014-04-17 05:58:57 +00:00
2018-05-05 21:58:11 +00:00
if ( sess - > eventlist . contains ( id ) ) {
2014-04-22 05:28:58 +00:00
return true ;
}
2014-09-17 06:12:38 +00:00
2018-05-05 21:58:11 +00:00
if ( sess - > m_valuesummary . contains ( id ) ) {
2014-06-20 02:06:57 +00:00
return true ;
}
2011-12-30 23:02:45 +00:00
}
2011-09-17 12:39:00 +00:00
}
2014-04-17 05:58:57 +00:00
2014-04-22 05:28:58 +00:00
return false ;
2011-08-07 11:37:56 +00:00
}
2011-07-27 09:21:53 +00:00
void Day : : OpenEvents ( )
2011-06-26 08:30:44 +00:00
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > type ( ) ! = MT_JOURNAL )
sess - > OpenEvents ( ) ;
2011-06-26 08:30:44 +00:00
}
2014-09-11 14:23:08 +00:00
d_events_open = true ;
2011-12-23 10:52:31 +00:00
}
2014-04-22 05:28:58 +00:00
2014-09-11 14:23:08 +00:00
void Day : : OpenSummary ( )
{
if ( d_summaries_open ) return ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
sess - > LoadSummary ( ) ;
2014-09-11 14:23:08 +00:00
}
d_summaries_open = true ;
}
2011-12-23 10:52:31 +00:00
void Day : : CloseEvents ( )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
sess - > TrashEvents ( ) ;
2011-12-23 10:52:31 +00:00
}
2014-09-11 14:23:08 +00:00
d_events_open = false ;
2011-06-26 08:30:44 +00:00
}
2011-12-28 12:36:40 +00:00
2014-08-20 18:36:44 +00:00
QList < ChannelID > Day : : getSortedMachineChannels ( MachineType type , quint32 chantype )
{
QList < ChannelID > available ;
2018-05-05 21:58:11 +00:00
auto mi_end = machines . end ( ) ;
for ( auto mi = machines . begin ( ) ; mi ! = mi_end ; mi + + ) {
2014-08-20 18:36:44 +00:00
if ( mi . key ( ) ! = type ) continue ;
available . append ( mi . value ( ) - > availableChannels ( chantype ) ) ;
}
QMultiMap < int , ChannelID > order ;
2018-05-05 21:58:11 +00:00
for ( const auto code : available ) {
2014-08-20 18:36:44 +00:00
order . insert ( schema : : channel [ code ] . order ( ) , code ) ;
}
QList < ChannelID > channels ;
2018-05-05 21:58:11 +00:00
for ( auto it = order . begin ( ) ; it ! = order . end ( ) ; + + it ) {
2014-08-20 18:36:44 +00:00
ChannelID code = it . value ( ) ;
channels . append ( code ) ;
}
return channels ;
}
2014-08-07 20:27:23 +00:00
QList < ChannelID > Day : : getSortedMachineChannels ( quint32 chantype )
{
2014-08-20 17:17:13 +00:00
QList < ChannelID > available ;
2018-05-05 21:58:11 +00:00
auto mi_end = machines . end ( ) ;
for ( auto mi = machines . begin ( ) ; mi ! = mi_end ; mi + + ) {
2014-08-20 17:17:13 +00:00
if ( mi . key ( ) = = MT_JOURNAL ) continue ;
available . append ( mi . value ( ) - > availableChannels ( chantype ) ) ;
}
2014-08-07 20:27:23 +00:00
QMultiMap < int , ChannelID > order ;
2018-05-05 21:58:11 +00:00
for ( auto code : available ) {
2014-08-07 20:27:23 +00:00
order . insert ( schema : : channel [ code ] . order ( ) , code ) ;
}
QList < ChannelID > channels ;
2018-05-05 21:58:11 +00:00
for ( auto it = order . begin ( ) ; it ! = order . end ( ) ; + + it ) {
2014-08-07 20:27:23 +00:00
ChannelID code = it . value ( ) ;
channels . append ( code ) ;
}
return channels ;
}
2014-08-20 17:17:13 +00:00
qint64 Day : : first ( MachineType type )
{
qint64 date = 0 ;
qint64 tmp ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( ( sess - > type ( ) = = type ) & & sess - > enabled ( ) ) {
tmp = sess - > first ( ) ;
2014-08-20 17:17:13 +00:00
if ( ! tmp ) { continue ; }
if ( ! date ) {
date = tmp ;
} else {
if ( tmp < date ) { date = tmp ; }
}
}
}
return date ;
}
2011-12-28 12:36:40 +00:00
qint64 Day : : first ( )
{
2014-04-17 05:58:57 +00:00
qint64 date = 0 ;
2011-12-28 12:36:40 +00:00
qint64 tmp ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > type ( ) = = MT_JOURNAL ) continue ;
if ( sess - > enabled ( ) ) {
tmp = sess - > first ( ) ;
2014-04-22 05:28:58 +00:00
if ( ! tmp ) { continue ; }
if ( ! date ) {
date = tmp ;
} else {
if ( tmp < date ) { date = tmp ; }
}
2011-12-28 12:36:40 +00:00
}
}
return date ;
}
//! \brief Returns the last session time of this day
qint64 Day : : last ( )
{
2014-04-17 05:58:57 +00:00
qint64 date = 0 ;
2011-12-28 12:36:40 +00:00
qint64 tmp ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > type ( ) = = MT_JOURNAL ) continue ;
if ( sess - > enabled ( ) ) {
tmp = sess - > last ( ) ;
2014-04-22 05:28:58 +00:00
if ( ! tmp ) { continue ; }
if ( ! date ) {
date = tmp ;
} else {
if ( tmp > date ) { date = tmp ; }
}
2011-12-28 12:36:40 +00:00
}
}
return date ;
}
2013-10-22 11:42:57 +00:00
2014-08-20 17:17:13 +00:00
qint64 Day : : last ( MachineType type )
{
qint64 date = 0 ;
qint64 tmp ;
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( ( sess - > type ( ) = = type ) & & sess - > enabled ( ) ) {
tmp = sess - > last ( ) ;
2014-08-20 17:17:13 +00:00
if ( ! tmp ) { continue ; }
if ( ! date ) {
date = tmp ;
} else {
if ( tmp > date ) { date = tmp ; }
}
}
}
return date ;
}
2014-07-25 07:53:48 +00:00
bool Day : : removeSession ( Session * sess )
2013-10-22 11:42:57 +00:00
{
2018-05-31 00:27:44 +00:00
sess - > machine ( ) - > sessionlist . remove ( sess - > session ( ) ) ;
2014-09-17 06:59:58 +00:00
MachineType mt = sess - > type ( ) ;
bool b = sessions . removeAll ( sess ) > 0 ;
if ( ! searchMachine ( mt ) ) {
machines . remove ( mt ) ;
}
return b ;
}
bool Day : : searchMachine ( MachineType mt ) {
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > type ( ) = = mt )
2014-09-17 06:59:58 +00:00
return true ;
}
return false ;
2014-07-25 07:53:48 +00:00
}
2018-04-28 05:33:26 +00:00
bool Day : : hasMachine ( Machine * mach )
{
2018-05-05 21:58:11 +00:00
for ( auto & sess : sessions ) {
if ( sess - > machine ( ) = = mach )
2018-04-28 05:33:26 +00:00
return true ;
}
return false ;
}
2014-09-17 06:59:58 +00:00
2014-07-25 07:53:48 +00:00
QString Day : : getCPAPMode ( )
{
2014-09-01 04:49:05 +00:00
Machine * mach = machine ( MT_CPAP ) ;
if ( ! mach ) return STR_MessageBox_Error ;
CPAPLoader * loader = qobject_cast < CPAPLoader * > ( mach - > loader ( ) ) ;
ChannelID modechan = loader - > CPAPModeChannel ( ) ;
schema : : Channel & chan = schema : : channel [ modechan ] ;
int mode = ( CPAPMode ) ( int ) qRound ( settings_wavg ( modechan ) ) ;
return chan . option ( mode ) ;
// if (mode == MODE_CPAP) {
// return QObject::tr("Fixed");
// } else if (mode == MODE_APAP) {
// return QObject::tr("Auto");
// } else if (mode == MODE_BILEVEL_FIXED ) {
// return QObject::tr("Fixed Bi-Level");
// } else if (mode == MODE_BILEVEL_AUTO_FIXED_PS) {
// return QObject::tr("Auto Bi-Level (Fixed PS)");
// } else if (mode == MODE_BILEVEL_AUTO_VARIABLE_PS) {
// return QObject::tr("Auto Bi-Level (Variable PS)");
// } else if (mode == MODE_ASV) {
// return QObject::tr("ASV Fixed EPAP");
// } else if (mode == MODE_ASV_VARIABLE_EPAP) {
// return QObject::tr("ASV Variable EPAP");
// }
// return STR_TR_Unknown;
2014-07-25 07:53:48 +00:00
}
2014-08-03 13:00:13 +00:00
QString Day : : getPressureRelief ( )
{
2014-08-20 17:17:13 +00:00
Machine * mach = machine ( MT_CPAP ) ;
if ( ! mach ) return STR_MessageBox_Error ;
CPAPLoader * loader = qobject_cast < CPAPLoader * > ( mach - > loader ( ) ) ;
2014-08-03 13:00:13 +00:00
if ( ! loader ) return STR_MessageBox_Error ;
QString pr_str ;
ChannelID pr_level_chan = loader - > PresReliefLevel ( ) ;
ChannelID pr_mode_chan = loader - > PresReliefMode ( ) ;
2014-08-04 19:57:48 +00:00
if ( ( pr_mode_chan ! = NoChannel ) & & settingExists ( pr_mode_chan ) ) {
2014-08-03 13:00:13 +00:00
int pr_mode = qRound ( settings_wavg ( pr_mode_chan ) ) ;
2014-08-04 19:57:48 +00:00
pr_str = QObject : : tr ( " %1%2 " ) . arg ( loader - > PresReliefLabel ( ) ) . arg ( schema : : channel [ pr_mode_chan ] . option ( pr_mode ) ) ;
int pr_level = - 1 ;
if ( pr_level_chan ! = NoChannel & & settingExists ( pr_level_chan ) ) {
pr_level = qRound ( settings_wavg ( pr_level_chan ) ) ;
}
if ( pr_level > = 0 ) pr_str + = QString ( " %1 " ) . arg ( schema : : channel [ pr_level_chan ] . option ( pr_level ) ) ;
2014-08-03 13:00:13 +00:00
} else pr_str = STR_TR_None ;
return pr_str ;
}
2014-07-25 07:53:48 +00:00
QString Day : : getPressureSettings ( )
{
2018-04-25 10:34:23 +00:00
if ( machine ( MT_CPAP ) = = nullptr ) {
qCritical ( " getPressureSettings called with no CPAP machine record " ) ;
return QString ( ) ;
}
2014-08-03 13:00:13 +00:00
2014-07-25 07:53:48 +00:00
CPAPMode mode = ( CPAPMode ) ( int ) settings_max ( CPAP_Mode ) ;
QString units = schema : : channel [ CPAP_Pressure ] . units ( ) ;
if ( mode = = MODE_CPAP ) {
2014-08-03 13:00:13 +00:00
return QObject : : tr ( " Fixed %1 (%2) " ) . arg ( settings_min ( CPAP_Pressure ) ) . arg ( units ) ;
2014-07-25 07:53:48 +00:00
} else if ( mode = = MODE_APAP ) {
2014-08-03 13:00:13 +00:00
return QObject : : tr ( " Min %1 Max %2 (%3) " ) . arg ( settings_min ( CPAP_PressureMin ) ) . arg ( settings_max ( CPAP_PressureMax ) ) . arg ( units ) ;
2014-07-25 07:53:48 +00:00
} else if ( mode = = MODE_BILEVEL_FIXED ) {
2014-08-05 22:31:31 +00:00
return QObject : : tr ( " EPAP %1 IPAP %2 (%3) " ) . arg ( settings_min ( CPAP_EPAP ) , 0 , ' f ' , 1 ) . arg ( settings_max ( CPAP_IPAP ) , 0 , ' f ' , 1 ) . arg ( units ) ;
2014-07-25 07:53:48 +00:00
} else if ( mode = = MODE_BILEVEL_AUTO_FIXED_PS ) {
2014-08-05 22:31:31 +00:00
return QObject : : tr ( " PS %1 over %2-%3 (%4) " ) . arg ( settings_max ( CPAP_PS ) , 0 , ' f ' , 1 ) . arg ( settings_min ( CPAP_EPAPLo ) , 0 , ' f ' , 1 ) . arg ( settings_max ( CPAP_IPAPHi ) , 0 , ' f ' , 1 ) . arg ( units ) ;
2014-08-03 13:00:13 +00:00
} else if ( mode = = MODE_BILEVEL_AUTO_VARIABLE_PS ) {
2014-08-05 22:31:31 +00:00
return QObject : : tr ( " Min EPAP %1 Max IPAP %2 PS %3-%4 (%5) " ) . arg ( settings_min ( CPAP_EPAPLo ) , 0 , ' f ' , 1 ) . arg ( settings_max ( CPAP_IPAPHi ) , 0 , ' f ' , 1 ) . arg ( settings_min ( CPAP_PSMin ) , 0 , ' f ' , 1 ) . arg ( settings_max ( CPAP_PSMax ) , 0 , ' f ' , 1 ) . arg ( units ) ;
2014-07-25 07:53:48 +00:00
} else if ( mode = = MODE_ASV ) {
2014-08-03 15:24:58 +00:00
return QObject : : tr ( " EPAP %1 PS %2-%3 (%6) " ) . arg ( settings_min ( CPAP_EPAP ) , 0 , ' f ' , 1 ) . arg ( settings_min ( CPAP_PSMin ) , 0 , ' f ' , 1 ) . arg ( settings_max ( CPAP_PSMax ) , 0 , ' f ' , 1 ) . arg ( units ) ;
2014-07-25 07:53:48 +00:00
} else if ( mode = = MODE_ASV_VARIABLE_EPAP ) {
2014-08-06 07:08:34 +00:00
return QObject : : tr ( " Min EPAP %1 Max IPAP %2 PS %3-%4 (%5) " ) .
arg ( settings_min ( CPAP_EPAPLo ) , 0 , ' f ' , 1 ) .
arg ( settings_max ( CPAP_IPAPHi ) , 0 , ' f ' , 1 ) .
arg ( settings_max ( CPAP_PSMin ) , 0 , ' f ' , 1 ) .
arg ( settings_min ( CPAP_PSMax ) , 0 , ' f ' , 1 ) .
arg ( units ) ;
2016-02-28 15:44:59 +00:00
} else if ( mode = = MODE_AVAPS ) {
return QObject : : tr ( " EPAP %1 IPAP %2 (%3) " ) . arg ( settings_min ( CPAP_EPAP ) , 0 , ' f ' , 1 ) . arg ( settings_max ( CPAP_IPAP ) , 0 , ' f ' , 1 ) . arg ( units ) ;
2014-07-25 07:53:48 +00:00
}
return STR_TR_Unknown ;
2013-10-22 11:42:57 +00:00
}
2014-08-17 12:56:05 +00:00
EventDataType Day : : calc ( ChannelID code , ChannelCalcType type )
{
EventDataType value ;
switch ( type ) {
case Calc_Min :
value = Min ( code ) ;
break ;
case Calc_Middle :
value = calcMiddle ( code ) ;
break ;
case Calc_Perc :
value = calcPercentile ( code ) ;
break ;
case Calc_Max :
value = calcMax ( code ) ;
break ;
case Calc_UpperThresh :
value = schema : : channel [ code ] . upperThreshold ( ) ;
break ;
case Calc_LowerThresh :
value = schema : : channel [ code ] . lowerThreshold ( ) ;
break ;
case Calc_Zero :
default :
value = 0 ;
break ;
} ;
return value ;
}