OSCAR-code/SleepLib/machine.cpp

619 lines
27 KiB
C++
Raw Normal View History

2011-07-01 10:10:44 +00:00
/*
2011-06-26 08:30:44 +00:00
SleepLib Machine Class Implementation
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
License: GPL
2011-07-01 10:10:44 +00:00
*/
2011-06-26 08:30:44 +00:00
2011-07-30 00:36:31 +00:00
#include <QApplication>
2011-07-01 10:10:44 +00:00
#include <QDir>
#include <QProgressBar>
#include <QDebug>
#include <QString>
#include <QObject>
2011-06-26 08:30:44 +00:00
#include <tr1/random>
#include <sys/time.h>
2011-06-26 08:30:44 +00:00
#include "machine.h"
#include "profiles.h"
#include <algorithm>
2011-06-27 06:26:29 +00:00
ChannelGroup CPAP_CODES;
ChannelGroup PRS1_CODES;
ChannelGroup RMS9_CODES;
ChannelGroup OXI_CODES;
ChannelGroup ZEO_CODES;
ChannelGroup JOURNAL_CODES;
ChannelID CPAP_Obstructive,CPAP_Hypopnea,CPAP_Apnea, CPAP_ClearAirway, CPAP_RERA, CPAP_FlowLimit,
CPAP_CSR, CPAP_VSnore, CPAP_PressurePulse, CPAP_Mode, CPAP_FlowRate, CPAP_MaskPressure, CPAP_Pressure,
CPAP_EPAP, CPAP_IPAP, CPAP_IPAP_Low, CPAP_IPAP_High, CPAP_PressureSupport, CPAP_Snore, CPAP_Leak,
CPAP_RespiratoryRate, CPAP_TidalVolume, CPAP_MinuteVentilation, CPAP_PatientTriggeredBreaths,
CPAP_FlowLimitGraph, CPAP_TherapyPressure, CPAP_ExpiratoryPressure, CPAP_AHI, CPAP_BrokenSummary,
CPAP_BrokenWaveform;
ChannelID RMS9_PressureReliefType, RMS9_PressureReliefSetting, RMS9_Empty1, RMS9_Empty2;
ChannelID PRS1_PressureMin,PRS1_PressureMax, PRS1_PressureMinAchieved, PRS1_PressureMaxAchieved,
PRS1_PressureAvg, PRS1_Pressure90, PRS1_RampTime, PRS1_RampPressure, PRS1_HumidifierStatus,
PRS1_HumidifierSetting, PRS1_PressureReliefType, PRS1_PressureReliefSetting, PRS1_SystemOneResistanceStatus,
PRS1_SystemOneResistanceSetting, PRS1_SystemLockStatus, PRS1_HoseDiameter, PRS1_AutoOff, PRS1_AutoOn,
PRS1_MaskAlert, PRS1_ShowAHI, PRS1_Unknown00, PRS1_Unknown01, PRS1_Unknown08, PRS1_Unknown09,
PRS1_Unknown0A, PRS1_Unknown0B, PRS1_Unknown0C, PRS1_Unknown0E, PRS1_Unknown0F, PRS1_Unknown10,
PRS1_Unknown12, PRS1_VSnore2;
ChannelID OXI_Pulse, OXI_SPO2, OXI_Plethysomogram, OXI_PulseChange, OXI_SPO2Drop, OXI_Error, OXI_SignalError;
ChannelID ZEO_SleepStage, ZEO_Waveform;
ChannelID JOURNAL_Notes, JOURNAL_Weight;
ChannelID ChannelGroup::Get(ChannelType ctype,QString description,QString label,QString lookup,QColor color)
{
ChannelID id=m_first+m_pos;
if (++m_pos>=m_size) {
qCritical("Not enough slots allocated for channel group");
abort();
}
channel[id]=Channel(id,m_type,ctype,description,label,color);
m_channelsbytype[ctype][id]=channel_lookup[lookup]=m_channel[id]=&channel[id];
2011-06-26 08:30:44 +00:00
return id;
}
ChannelGroup::ChannelGroup()
{
m_pos=0; m_first=0xf000, m_size=0x1000;
}
ChannelGroup::ChannelGroup(MachineType type, ChannelID first, ChannelID reserved)
:m_type(type),m_first(first),m_size(reserved)
{
m_pos=0;
}
2011-06-26 08:30:44 +00:00
extern QProgressBar * qprogress;
2011-06-26 08:30:44 +00:00
// Master Lists..
QHash<ChannelID, Channel> channel;
QHash<QString,Channel *> channel_lookup;
QHash<QString,ChannelGroup *> channel_group;
2011-06-26 08:30:44 +00:00
void InitMapsWithoutAwesomeInitializerLists()
{
CPAP_CODES=ChannelGroup(MT_CPAP,0x1000,0x400);
PRS1_CODES=ChannelGroup(MT_CPAP,0x1400,0x200);
RMS9_CODES=ChannelGroup(MT_CPAP,0x1600,0x200);
OXI_CODES=ChannelGroup(MT_OXIMETER,0x2000,0x800);
ZEO_CODES=ChannelGroup(MT_SLEEPSTAGE,0x2800,0x800);
JOURNAL_CODES=ChannelGroup(MT_JOURNAL,0x3000,0x800);
// ******************** IMPORTANT ********************
// Add to the end of each group or be eaten by a Grue!
// ******************** IMPORTANT ********************
// Flagable Events
CPAP_Obstructive=CPAP_CODES.Get(CT_Event,QObject::tr("Obstructive Apnea"),QObject::tr("OA"),"OA"),
CPAP_Hypopnea=CPAP_CODES.Get(CT_Event,QObject::tr("Hypopnea"),QObject::tr("H"),"OA"),
CPAP_Apnea=CPAP_CODES.Get(CT_Event,QObject::tr("Unspecified Apnea"),QObject::tr("UA"),"UA"),
CPAP_ClearAirway=CPAP_CODES.Get(CT_Event,QObject::tr("Clear Airway Apnea"),QObject::tr("CA"),"CA"),
CPAP_RERA=CPAP_CODES.Get(CT_Event,QObject::tr("Respiratory Effort Related Arousal"),QObject::tr("RE"),"RE"),
CPAP_FlowLimit=CPAP_CODES.Get(CT_Event,QObject::tr("Flow Limitation"),QObject::tr("FL"),"FL"),
CPAP_CSR=CPAP_CODES.Get(CT_Event,QObject::tr("Periodic Breathing"),QObject::tr("PB"),"PB"),
CPAP_VSnore=CPAP_CODES.Get(CT_Event,QObject::tr("Vibratory Snore"),QObject::tr("VS"),"VS"),
CPAP_PressurePulse=CPAP_CODES.Get(CT_Event,QObject::tr("Pressure Pulse"),QObject::tr("PP"),"PP"),
CPAP_Mode=CPAP_CODES.Get(CT_Lookup,QObject::tr("CPAP Mode"),QObject::tr("CPAPMode"),"CPAPMode"),
// Alternate names at the end of each section
// Graphable Events & Waveforms
CPAP_FlowRate=CPAP_CODES.Get(CT_Graph,QObject::tr("Flow Rate Waveform"),QObject::tr("Flow Rate"),"FR"),
CPAP_MaskPressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Mask Pressure"),QObject::tr("Mask Pressure"),"MP"),
CPAP_Pressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Pressure"),QObject::tr("Pressure"),"P"),
CPAP_EPAP=CPAP_CODES.Get(CT_Graph,QObject::tr("Expiratory Pressure"),QObject::tr("EPAP"),"EPAP"),
CPAP_IPAP=CPAP_CODES.Get(CT_Graph,QObject::tr("Inhalation Pressure"),QObject::tr("IPAP"),"IPAP"),
CPAP_IPAP_Low=CPAP_CODES.Get(CT_Graph,QObject::tr("IPAP Low"),QObject::tr("IPAP Low"),"IPAPL"),
CPAP_IPAP_High=CPAP_CODES.Get(CT_Graph,QObject::tr("IPAP Low"),QObject::tr("IPAP High"),"IPAPH"),
CPAP_PressureSupport=CPAP_CODES.Get(CT_Graph,QObject::tr("Pressure Support"),QObject::tr("Pressure Support"),"PS"),
CPAP_Snore=CPAP_CODES.Get(CT_Graph,QObject::tr("Snore"),QObject::tr("Snore"),"Snore"),
CPAP_Leak=CPAP_CODES.Get(CT_Graph,QObject::tr("Leak Rate"),QObject::tr("Leak Rate"),"Leak"),
CPAP_RespiratoryRate=CPAP_CODES.Get(CT_Graph,QObject::tr("Respiratory Rate"),QObject::tr("Respiratory Rate"),"RR"),
CPAP_TidalVolume=CPAP_CODES.Get(CT_Graph,QObject::tr("Tidal Volume"),QObject::tr("Tidal Volume"),"TV"),
CPAP_MinuteVentilation=CPAP_CODES.Get(CT_Graph,QObject::tr("Minute Ventilation"),QObject::tr("Minute Ventilation"),"MV"),
CPAP_PatientTriggeredBreaths=CPAP_CODES.Get(CT_Graph,QObject::tr("Patient Triggered Breaths"),QObject::tr("Patient Trig Breaths"),"PTB"),
CPAP_FlowLimitGraph=CPAP_CODES.Get(CT_Graph,QObject::tr("Flow Limitation Graph"),QObject::tr("Flow Limitation"),"FLG"),
CPAP_TherapyPressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Therapy Pressure"),QObject::tr("Therapy Pressure"),"TP"),
CPAP_ExpiratoryPressure=CPAP_CODES.Get(CT_Graph,QObject::tr("Expiratory Pressure"),QObject::tr("Expiratory Pressure"),"EXP"),
CPAP_AHI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Apnea-Hypopnea Index"),QObject::tr("AHI"),"AHI"),
/*CPAP_AI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Apnea Index"),QObject::tr("AI"),"AI"),
CPAP_HI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Hypopnea Index"),QObject::tr("HI"),"HI"),
CPAP_CAI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Central Apnea Index"),QObject::tr("CAI"),"CAI"),
CPAP_RAI=CPAP_CODES.Get(CT_Calculation,QObject::tr("RERA+AHI Index"),QObject::tr("RAI"),"RAI"),
CPAP_RI=CPAP_CODES.Get(CT_Calculation,QObject::tr("RERA Index"),QObject::tr("RI"),"RI"),
CPAP_FLI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Flow Limitation Index"),QObject::tr("FLI"),"FLI"),
CPAP_VSI=CPAP_CODES.Get(CT_Calculation,QObject::tr("Vibratory Snore Index"),QObject::tr("VSI"),"VSI"),
CPAP_PBI=CPAP_CODES.Get(CT_Calculation,QObject::tr("% Night in Periodic Breathing"),QObject::tr("PBI"),"PBI"), */
//CPAP_PressureReliefType=CPAP_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Type"),"","PRType"),
//CPAP_PressureReliefSetting=CPAP_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Setting"),"","PRSet"),
CPAP_BrokenSummary=CPAP_CODES.Get(CT_Boolean,QObject::tr("Broken Summary"),QObject::tr(""),"BrokenSummary"),
CPAP_BrokenWaveform=CPAP_CODES.Get(CT_Boolean,QObject::tr("Broken Waveform"),QObject::tr(""),"BrokenWaveform");
RMS9_PressureReliefType=RMS9_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Type"),"","RMS9_PRType"),
RMS9_PressureReliefSetting=RMS9_CODES.Get(CT_Decimal,QObject::tr("Pressure Relief Setting"),"","RMS9_PRSet"),
RMS9_Empty1=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown Empty 1"),"","RMS9_UE1"),
RMS9_Empty2=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown Empty 2"),"","RMS9_UE2"),
PRS1_PressureMin=PRS1_CODES.Get(CT_Decimal,QObject::tr("Minimum Pressure"),"","PRS1_MinPres"),
PRS1_PressureMax=PRS1_CODES.Get(CT_Decimal,QObject::tr("Maximum Pressure"),"","PRS1_MaxPres"),
PRS1_PressureMinAchieved=PRS1_CODES.Get(CT_Decimal,QObject::tr("Minimum Pressure Achieved"),"","PRS1_MinPresAch"),
PRS1_PressureMaxAchieved=PRS1_CODES.Get(CT_Decimal,QObject::tr("Maximum Pressure Achieved"),"","PRS1_MaxPresAch"),
PRS1_PressureAvg=PRS1_CODES.Get(CT_Decimal,QObject::tr("Average Pressure"),"","PRS1_AvgPres"),
PRS1_Pressure90=PRS1_CODES.Get(CT_Decimal,QObject::tr("90% Pressure"),"","PRS1_90Pres"),
PRS1_RampTime=PRS1_CODES.Get(CT_Timespan,QObject::tr("Ramp Time"),"","PRS1_RampTime"),
PRS1_RampPressure=PRS1_CODES.Get(CT_Decimal,QObject::tr("Ramp Pressure"),"","PRS1_RampPressure"),
PRS1_HumidifierStatus=PRS1_CODES.Get(CT_Boolean,QObject::tr("Humidifier Status"),"","PRS1_HumiStat"),
PRS1_HumidifierSetting=PRS1_CODES.Get(CT_Lookup,QObject::tr("Humidifier Setting"),"","PRS1_HumiSet"),
PRS1_PressureReliefType=PRS1_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Type"),"","PRS1_PRType"),
PRS1_PressureReliefSetting=PRS1_CODES.Get(CT_Lookup,QObject::tr("Pressure Relief Setting"),"","PRS1_PRSet"),
PRS1_SystemOneResistanceStatus=PRS1_CODES.Get(CT_Boolean,QObject::tr("System-One Resistance Status"),"","PRS1_ResistStat"),
PRS1_SystemOneResistanceSetting=PRS1_CODES.Get(CT_Lookup,QObject::tr("System-One Resistance Setting"),"","PRS1_ResistSet"),
PRS1_SystemLockStatus=PRS1_CODES.Get(CT_Boolean,QObject::tr("System Lock Status"),"","PRS1_SysLockStat"),
PRS1_HoseDiameter=PRS1_CODES.Get(CT_Lookup,QObject::tr("Hose Diameter"),"","PRS1_HoseDiam"),
PRS1_AutoOff=PRS1_CODES.Get(CT_Boolean,QObject::tr("Auto Off"),"","PRS1_AutoOff"),
PRS1_AutoOn=PRS1_CODES.Get(CT_Boolean,QObject::tr("Auto On"),"","PRS1_AutoOn"),
PRS1_MaskAlert=PRS1_CODES.Get(CT_Boolean,QObject::tr("Mask Alert"),"","PRS1_MaskAlert"),
PRS1_ShowAHI=PRS1_CODES.Get(CT_Boolean,QObject::tr("Show AHI"),"","PRS1_ShowAHI"),
PRS1_Unknown00=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 00 Event"),QObject::tr("U00"),"PRS1_U00"),
PRS1_Unknown01=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 01 Event"),QObject::tr("U01"),"PRS1_U01"),
PRS1_Unknown08=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 08 Event"),QObject::tr("U08"),"PRS1_U08"),
PRS1_Unknown09=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 09 Event"),QObject::tr("U09"),"PRS1_U09"),
PRS1_Unknown0A=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0A Event"),QObject::tr("U0A"),"PRS1_U0A"),
PRS1_Unknown0B=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0B Event"),QObject::tr("U0B"),"PRS1_U0B"),
PRS1_Unknown0C=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0C Event"),QObject::tr("U0C"),"PRS1_U0C"),
PRS1_Unknown0E=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0E Event"),QObject::tr("U0E"),"PRS1_U0E"),
PRS1_Unknown0F=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 0F Event"),QObject::tr("U0F"),"PRS1_U0F"),
PRS1_Unknown10=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 10 Event"),QObject::tr("U10"),"PRS1_U10"),
PRS1_Unknown12=CPAP_CODES.Get(CT_Event,QObject::tr("Unknown 12 Event"),QObject::tr("U12"),"PRS1_U12"),
PRS1_VSnore2=CPAP_CODES.Get(CT_Event,QObject::tr("Vibratory Snore (Type 2)"),QObject::tr("VS2"),"VS2");
OXI_Pulse=OXI_CODES.Get(CT_Graph,QObject::tr("Pulse Rate"),QObject::tr("PR"),"PR"),
OXI_SPO2=OXI_CODES.Get(CT_Graph,QObject::tr("Oxygen Saturation"),QObject::tr("SPO2"),"SPO2"),
OXI_Plethysomogram=OXI_CODES.Get(CT_Graph,QObject::tr("Plethysomogram"),QObject::tr("PLE"),"PLE"),
OXI_PulseChange=OXI_CODES.Get(CT_Event,QObject::tr("Pulse Change"),QObject::tr("PC"),"PC"),
OXI_SPO2Drop=OXI_CODES.Get(CT_Event,QObject::tr("Oxigen Saturation Drop"),QObject::tr("SD"),"SD"),
OXI_Error=OXI_CODES.Get(CT_Event,QObject::tr("Oximeter Error"),QObject::tr("ER1"),"ER1"),
OXI_SignalError=OXI_CODES.Get(CT_Event,QObject::tr("Oximeter Signal Error"),QObject::tr("ER2"),"ER2");
ZEO_SleepStage=ZEO_CODES.Get(CT_Graph,QObject::tr("Sleep Stage"),QObject::tr("SS"),"SS"),
ZEO_Waveform=ZEO_CODES.Get(CT_Graph,QObject::tr("Brainwaves"),QObject::tr("BW"),"BW");
JOURNAL_Notes=JOURNAL_CODES.Get(CT_Text,"Journal/Notes","JN"),
JOURNAL_Weight=JOURNAL_CODES.Get(CT_Decimal,"Weight","W");
channel[CPAP_Mode].addOption("CPAP");
channel[CPAP_Mode].addOption("Auto");
channel[CPAP_Mode].addOption("BIPAP/VPAP");
channel[CPAP_Mode].addOption("ASV");
channel[PRS1_HoseDiameter].addOption("22mm");
channel[PRS1_HoseDiameter].addOption("15mm");
channel[PRS1_HumidifierSetting].addOption("Off");
channel[PRS1_HumidifierSetting].addOption("1");
channel[PRS1_HumidifierSetting].addOption("2");
channel[PRS1_HumidifierSetting].addOption("3");
channel[PRS1_HumidifierSetting].addOption("4");
channel[PRS1_HumidifierSetting].addOption("5");
channel[PRS1_SystemOneResistanceSetting].addOption("x1");
channel[PRS1_SystemOneResistanceSetting].addOption("x2");
channel[PRS1_SystemOneResistanceSetting].addOption("x3");
channel[PRS1_SystemOneResistanceSetting].addOption("x4");
channel[PRS1_SystemOneResistanceSetting].addOption("x5");
channel[PRS1_PressureReliefType].addOption("None");
channel[PRS1_PressureReliefType].addOption("C-Flex");
channel[PRS1_PressureReliefType].addOption("C-Flex+");
channel[PRS1_PressureReliefType].addOption("A-Flex");
channel[PRS1_PressureReliefType].addOption("Bi-Flex");
channel[PRS1_PressureReliefType].addOption("Bi-Flex+");
channel[PRS1_PressureReliefSetting].addOption("Off");
channel[PRS1_PressureReliefSetting].addOption("1");
channel[PRS1_PressureReliefSetting].addOption("2");
channel[PRS1_PressureReliefSetting].addOption("3");
channel[RMS9_PressureReliefType].addOption("None");
channel[RMS9_PressureReliefType].addOption("EPR");
channel[RMS9_PressureReliefSetting].addOption("0");
channel[RMS9_PressureReliefSetting].addOption("0.5");
channel[RMS9_PressureReliefSetting].addOption("1");
channel[RMS9_PressureReliefSetting].addOption("1.5");
channel[RMS9_PressureReliefSetting].addOption("2");
channel[RMS9_PressureReliefSetting].addOption("2.5");
channel[RMS9_PressureReliefSetting].addOption("3.0");
channel[ZEO_SleepStage].addOption("Unknown");
channel[ZEO_SleepStage].addOption("Awake");
channel[ZEO_SleepStage].addOption("REM");
channel[ZEO_SleepStage].addOption("Light Sleep");
channel[ZEO_SleepStage].addOption("Deep Sleep");
/* CPAPModeNames[MODE_UNKNOWN]=QObject::tr("Undetermined");
2011-07-01 10:10:44 +00:00
CPAPModeNames[MODE_CPAP]=QObject::tr("CPAP");
CPAPModeNames[MODE_APAP]=QObject::tr("Auto");
CPAPModeNames[MODE_BIPAP]=QObject::tr("BIPAP");
CPAPModeNames[MODE_ASV]=QObject::tr("ASV");
PressureReliefNames[PR_UNKNOWN]=QObject::tr("Undetermined");
PressureReliefNames[PR_NONE]=QObject::tr("None");
PressureReliefNames[PR_CFLEX]=QObject::tr("C-Flex");
PressureReliefNames[PR_CFLEXPLUS]=QObject::tr("C-Flex+");
PressureReliefNames[PR_AFLEX]=QObject::tr("A-Flex");
PressureReliefNames[PR_BIFLEX]=QObject::tr("Bi-Flex");
PressureReliefNames[PR_EPR]=QObject::tr("Exhalation Pressure Relief (EPR)");
PressureReliefNames[PR_SMARTFLEX]=QObject::tr("SmartFlex");
DefaultMCShortNames[CPAP_Obstructive]=QObject::tr("OA");
DefaultMCShortNames[CPAP_Apnea]=QObject::tr("A");
2011-07-01 10:10:44 +00:00
DefaultMCShortNames[CPAP_Hypopnea]=QObject::tr("H");
DefaultMCShortNames[CPAP_RERA]=QObject::tr("RE");
DefaultMCShortNames[CPAP_ClearAirway]=QObject::tr("CA");
DefaultMCShortNames[CPAP_CSR]=QObject::tr("CSR/PB");
DefaultMCShortNames[CPAP_VSnore]=QObject::tr("VS");
DefaultMCShortNames[PRS1_VSnore2]=QObject::tr("VS2");
DefaultMCShortNames[CPAP_FlowLimit]=QObject::tr("FL");
DefaultMCShortNames[CPAP_Pressure]=QObject::tr("P");
DefaultMCShortNames[CPAP_Leak]=QObject::tr("LR");
DefaultMCShortNames[CPAP_EAP]=QObject::tr("EPAP");
DefaultMCShortNames[CPAP_IAP]=QObject::tr("IPAP");
DefaultMCShortNames[PRS1_PressurePulse]=QObject::tr("PP");
DefaultMCLongNames[CPAP_Obstructive]=QObject::tr("Obstructive Apnea");
DefaultMCLongNames[CPAP_Hypopnea]=QObject::tr("Hypopnea");
DefaultMCLongNames[CPAP_Apnea]=QObject::tr("Apnea");
2011-07-01 10:10:44 +00:00
DefaultMCLongNames[CPAP_RERA]=QObject::tr("RERA");
DefaultMCLongNames[CPAP_ClearAirway]=QObject::tr("Clear Airway Apnea");
DefaultMCLongNames[CPAP_CSR]=QObject::tr("Periodic Breathing");
DefaultMCLongNames[CPAP_VSnore]=QObject::tr("Vibratory Snore"); // flags type
DefaultMCLongNames[CPAP_FlowLimit]=QObject::tr("Flow Limitation");
DefaultMCLongNames[CPAP_Pressure]=QObject::tr("Pressure");
DefaultMCLongNames[CPAP_Leak]=QObject::tr("Leak Rate");
DefaultMCLongNames[CPAP_PS]=QObject::tr("Pressure Support");
2011-07-01 10:10:44 +00:00
DefaultMCLongNames[CPAP_EAP]=QObject::tr("BIPAP EPAP");
DefaultMCLongNames[CPAP_IAP]=QObject::tr("BIPAP IPAP");
DefaultMCLongNames[CPAP_Snore]=QObject::tr("Vibratory Snore"); // Graph data
DefaultMCLongNames[PRS1_VSnore2]=QObject::tr("Vibratory Snore (Graph)");
DefaultMCLongNames[PRS1_PressurePulse]=QObject::tr("Pressure Pulse");
DefaultMCLongNames[PRS1_Unknown0E]=QObject::tr("Unknown 0E");
DefaultMCLongNames[PRS1_Unknown00]=QObject::tr("Unknown 00");
DefaultMCLongNames[PRS1_Unknown01]=QObject::tr("Unknown 01");
DefaultMCLongNames[PRS1_Unknown0B]=QObject::tr("Unknown 0B");
DefaultMCLongNames[PRS1_Unknown10]=QObject::tr("Unknown 10"); */
2011-06-26 08:30:44 +00:00
}
//////////////////////////////////////////////////////////////////////////////////////////
// Machine Base-Class implmementation
//////////////////////////////////////////////////////////////////////////////////////////
Machine::Machine(Profile *p,MachineID id)
{
day.clear();
highest_sessionid=0;
profile=p;
if (!id) {
std::tr1::minstd_rand gen;
std::tr1::uniform_int<MachineID> unif(1, 0x7fffffff);
gen.seed((unsigned int) time(NULL));
MachineID temp;
do {
temp = unif(gen); //unif(gen) << 32 |
} while (profile->machlist.find(temp)!=profile->machlist.end());
m_id=temp;
} else m_id=id;
2011-07-01 10:10:44 +00:00
qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id);
2011-06-26 08:30:44 +00:00
m_type=MT_UNKNOWN;
firstsession=true;
}
Machine::~Machine()
{
2011-07-01 10:10:44 +00:00
qDebug() << "Destroy Machine";
for (QMap<QDate,Day *>::iterator d=day.begin();d!=day.end();d++) {
delete d.value();
2011-06-26 08:30:44 +00:00
}
}
Session *Machine::SessionExists(SessionID session)
{
if (sessionlist.find(session)!=sessionlist.end()) {
return sessionlist[session];
} else {
return NULL;
}
}
2011-06-26 08:30:44 +00:00
Day *Machine::AddSession(Session *s,Profile *p)
{
2011-07-03 03:38:55 +00:00
double span=0;
if (!s) {
qWarning() << "Empty Session in Machine::AddSession()";
return NULL;
}
if (!p) {
qWarning() << "Empty Profile in Machine::AddSession()";
return NULL;
}
2011-06-26 08:30:44 +00:00
if (s->session()>highest_sessionid)
highest_sessionid=s->session();
2011-08-05 07:52:32 +00:00
QTime split_time(12,0,0);
if (pref.Exists("DaySplitTime")) {
split_time=pref["DaySplitTime"].toTime();
}
int combine_sessions;
if (pref.Exists("CombineCloserSessions")) {
combine_sessions=pref["CombineCloserSessions"].toInt(); // In Minutes
} else combine_sessions=0;
2011-08-05 07:52:32 +00:00
int ignore_sessions;
if (pref.Exists("IgnoreShorterSessions")) {
ignore_sessions=pref["IgnoreShorterSessions"].toInt(); // In Minutes
} else ignore_sessions=0;
2011-08-05 07:52:32 +00:00
int session_length=s->last()-s->first();
session_length/=60000;
2011-08-05 07:52:32 +00:00
sessionlist[s->session()]=s; // To make sure it get's saved later even if it's not wanted.
2011-07-03 08:08:14 +00:00
2011-08-05 07:52:32 +00:00
QDateTime d1,d2=QDateTime::fromMSecsSinceEpoch(s->first());
2011-06-26 08:30:44 +00:00
2011-08-05 07:52:32 +00:00
QDate date=d2.date();
QTime time=d2.time();
2011-06-26 08:30:44 +00:00
2011-08-05 07:52:32 +00:00
QMap<QDate,Day *>::iterator dit,nextday;
2011-06-26 08:30:44 +00:00
2011-08-05 07:52:32 +00:00
bool combine_next_day=false;
int closest_session=0;
2011-07-03 03:38:55 +00:00
2011-08-05 07:52:32 +00:00
if (time<split_time) {
date=date.addDays(-1);
} else if (combine_sessions > 0) {
dit=day.find(date.addDays(-1)); // Check Day Before
if (dit!=day.end()) {
QDateTime lt=QDateTime::fromMSecsSinceEpoch(dit.value()->last());
closest_session=lt.secsTo(d2)/60;
if (closest_session<combine_sessions) {
date=date.addDays(-1);
}
} else {
nextday=day.find(date.addDays(1));// Check Day Afterwards
if (nextday!=day.end()) {
QDateTime lt=QDateTime::fromMSecsSinceEpoch(nextday.value()->first());
closest_session=d2.secsTo(lt)/60;
if (closest_session < combine_sessions) {
// add todays here. pull all tomorrows records to this date.
combine_next_day=true;
}
2011-07-03 08:08:14 +00:00
}
}
2011-06-26 08:30:44 +00:00
}
if (session_length<ignore_sessions) {
//if (!closest_session || (closest_session>=60))
return NULL;
}
2011-06-26 08:30:44 +00:00
if (!firstsession) {
if (firstday>date) firstday=date;
if (lastday<date) lastday=date;
} else {
firstday=lastday=date;
firstsession=false;
}
2011-07-03 08:08:14 +00:00
Day *dd=NULL;
dit=day.find(date);
if (dit==day.end()) {
//QString dstr=date.toString("yyyyMMdd");
//qDebug("Adding Profile Day %s",dstr.toAscii().data());
dd=new Day(this);
day[date]=dd;
2011-06-26 08:30:44 +00:00
// Add this Day record to profile
//QDateTime d=QDateTime::fromMSecsSinceEpoch(date);
//qDebug() << "New day: " << d.toString("yyyy-MM-dd HH:mm:ss");
p->AddDay(date,dd,m_type);
} else {
dd=*dit;
2011-06-26 08:30:44 +00:00
}
dd->AddSession(s);
2011-06-26 08:30:44 +00:00
2011-08-05 07:52:32 +00:00
if (combine_next_day) {
for (QVector<Session *>::iterator i=nextday.value()->begin();i!=nextday.value()->end();i++) {
dd->AddSession(*i);
}
QMap<QDate,QVector<Day *> >::iterator nd=p->daylist.find(date.addDays(1));
for (QVector<Day *>::iterator i=nd->begin();i!=nd->end();i++) {
if (*i==nextday.value()) {
nd.value().erase(i);
}
}
day.erase(nextday);
}
return dd;
2011-06-26 08:30:44 +00:00
}
// This functions purpose is murder and mayhem... It deletes all of a machines data.
// Therefore this is the most dangerous function in this software..
bool Machine::Purge(int secret)
{
// Boring api key to stop this function getting called by accident :)
if (secret!=3478216) return false;
// It would be joyous if this function screwed up..
QString path=profile->Get("DataFolder")+"/"+hexid();
QDir dir(path);
if (!dir.exists() || !dir.isReadable())
return false;
2011-07-01 10:10:44 +00:00
qDebug() << "Purging " << QDir::toNativeSeparators(path);
2011-06-26 08:30:44 +00:00
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
dir.setSorting(QDir::Name);
QFileInfoList list=dir.entryInfoList();
int could_not_kill=0;
for (int i=0;i<list.size();++i) {
QFileInfo fi=list.at(i);
QString fullpath=fi.canonicalFilePath();
//int j=fullpath.lastIndexOf(".");
QString ext_s=fullpath.section('.',-1);//right(j);
2011-06-26 08:30:44 +00:00
bool ok;
2011-07-01 10:10:44 +00:00
ext_s.toInt(&ok,10);
2011-06-26 08:30:44 +00:00
if (ok) {
qDebug() << "Deleting " << fullpath;
2011-06-26 08:30:44 +00:00
dir.remove(fullpath);
} else could_not_kill++;
}
if (could_not_kill>0) {
2011-07-01 10:10:44 +00:00
qWarning() << "Could not purge path\n" << path << "\n\n" << could_not_kill << " file(s) remain.. Suggest manually deleting this path\n";
2011-06-26 08:30:44 +00:00
return false;
}
return true;
}
bool Machine::Load()
{
QString path=profile->Get("DataFolder")+"/"+hexid();
QDir dir(path);
2011-07-01 10:10:44 +00:00
qDebug() << "Loading " << path;
2011-06-26 08:30:44 +00:00
if (!dir.exists() || !dir.isReadable())
return false;
dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
dir.setSorting(QDir::Name);
QFileInfoList list=dir.entryInfoList();
typedef QVector<QString> StringList;
QMap<SessionID,StringList> sessfiles;
QMap<SessionID,StringList>::iterator s;
2011-06-26 08:30:44 +00:00
QString fullpath,ext_s,sesstr;
int ext;
SessionID sessid;
bool ok;
for (int i=0;i<list.size();i++) {
QFileInfo fi=list.at(i);
fullpath=fi.canonicalFilePath();
ext_s=fi.fileName().section(".",-1);
ext=ext_s.toInt(&ok,10);
if (!ok) continue;
sesstr=fi.fileName().section(".",0,-2);
sessid=sesstr.toLong(&ok,16);
if (!ok) continue;
if (sessfiles[sessid].capacity()==0) sessfiles[sessid].resize(3);
sessfiles[sessid][ext]=fi.canonicalFilePath();
}
2011-06-27 06:26:29 +00:00
int size=sessfiles.size();
int cnt=0;
2011-06-26 08:30:44 +00:00
for (s=sessfiles.begin(); s!=sessfiles.end(); s++) {
2011-06-27 07:45:59 +00:00
cnt++;
if ((cnt % 10)==0)
if (qprogress) qprogress->setValue((float(cnt)/float(size)*100.0));
Session *sess=new Session(this,s.key());
2011-06-26 08:30:44 +00:00
if (sess->LoadSummary(s.value()[0])) {
sess->SetEventFile(s.value()[1]);
AddSession(sess,profile);
} else {
2011-07-03 11:49:47 +00:00
qWarning() << "Error unpacking summary data";
2011-06-26 08:30:44 +00:00
delete sess;
}
}
2011-06-27 07:45:59 +00:00
if (qprogress) qprogress->setValue(100);
2011-06-26 08:30:44 +00:00
return true;
}
bool Machine::SaveSession(Session *sess)
{
QString path=profile->Get("DataFolder")+"/"+hexid();
if (sess->IsChanged()) sess->Store(path);
2011-07-01 10:10:44 +00:00
return true;
2011-06-26 08:30:44 +00:00
}
bool Machine::Save()
{
int size=0;
int cnt=0;
QString path=profile->Get("DataFolder")+"/"+hexid();
// Calculate size for progress bar
2011-08-05 07:52:32 +00:00
size=sessionlist.size();
2011-06-26 08:30:44 +00:00
2011-08-05 07:52:32 +00:00
QHash<SessionID,Session *>::iterator s;
2011-08-05 07:52:32 +00:00
for (s=sessionlist.begin(); s!=sessionlist.end(); s++) {
cnt++;
if (qprogress) qprogress->setValue(66.0+(float(cnt)/float(size)*33.0));
if ((*s)->IsChanged()) (*s)->Store(path);
(*s)->TrashEvents();
QApplication::processEvents();
2011-06-26 08:30:44 +00:00
}
return true;
}
//////////////////////////////////////////////////////////////////////////////////////////
// CPAP implmementation
//////////////////////////////////////////////////////////////////////////////////////////
CPAP::CPAP(Profile *p,MachineID id):Machine(p,id)
{
m_type=MT_CPAP;
// FlagColours=DefaultFlagColours;
}
CPAP::~CPAP()
{
}
//////////////////////////////////////////////////////////////////////////////////////////
// Oximeter Class implmementation
//////////////////////////////////////////////////////////////////////////////////////////
Oximeter::Oximeter(Profile *p,MachineID id):Machine(p,id)
{
m_type=MT_OXIMETER;
}
Oximeter::~Oximeter()
{
}
//////////////////////////////////////////////////////////////////////////////////////////
// SleepStage Class implmementation
//////////////////////////////////////////////////////////////////////////////////////////
SleepStage::SleepStage(Profile *p,MachineID id):Machine(p,id)
{
m_type=MT_SLEEPSTAGE;
}
SleepStage::~SleepStage()
{
}