mirror of
https://gitlab.com/pholy/OSCAR-code.git
synced 2025-04-06 03:00:43 +00:00
Importer will be temporarily slow due to creating craploads of new indexes. Lots of bugs fixed.. Probably lots of new bugs too! Replaced slow map containers with fast QHash containers. Plus plenty of other mind numbing stuff.
601 lines
26 KiB
C++
601 lines
26 KiB
C++
/*
|
|
SleepLib Machine Class Implementation
|
|
Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
|
|
License: GPL
|
|
*/
|
|
|
|
#include <QApplication>
|
|
#include <QDir>
|
|
#include <QProgressBar>
|
|
#include <QDebug>
|
|
#include <QString>
|
|
#include <QObject>
|
|
#include <tr1/random>
|
|
#include <sys/time.h>
|
|
|
|
#include "machine.h"
|
|
#include "profiles.h"
|
|
#include <algorithm>
|
|
|
|
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)
|
|
{
|
|
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);
|
|
m_channelsbytype[ctype][id]=channel_lookup[lookup]=m_channel[id]=&channel[id];
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
extern QProgressBar * qprogress;
|
|
|
|
// Master Lists..
|
|
QHash<ChannelID, Channel> channel;
|
|
QHash<QString,Channel *> channel_lookup;
|
|
QHash<QString,ChannelGroup *> channel_group;
|
|
|
|
|
|
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");
|
|
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");
|
|
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");
|
|
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");
|
|
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"); */
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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;
|
|
qDebug() << "Create Machine: " << hex << m_id; //%lx",m_id);
|
|
m_type=MT_UNKNOWN;
|
|
firstsession=true;
|
|
}
|
|
Machine::~Machine()
|
|
{
|
|
qDebug() << "Destroy Machine";
|
|
for (QMap<QDate,Day *>::iterator d=day.begin();d!=day.end();d++) {
|
|
delete d.value();
|
|
}
|
|
}
|
|
Session *Machine::SessionExists(SessionID session)
|
|
{
|
|
if (sessionlist.find(session)!=sessionlist.end()) {
|
|
return sessionlist[session];
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
Day *Machine::AddSession(Session *s,Profile *p)
|
|
{
|
|
double span=0;
|
|
if (!s) {
|
|
qWarning() << "Empty Session in Machine::AddSession()";
|
|
return NULL;
|
|
}
|
|
if (!p) {
|
|
qWarning() << "Empty Profile in Machine::AddSession()";
|
|
return NULL;
|
|
}
|
|
if (s->session()>highest_sessionid)
|
|
highest_sessionid=s->session();
|
|
|
|
QDateTime d1,d2=QDateTime::fromMSecsSinceEpoch(s->first());
|
|
|
|
QDate date=d2.date();
|
|
//QTime time=d2.time();
|
|
|
|
if (pref.Exists("NoonDataSplit") && pref["NoonDateSplit"].toBool()) {
|
|
int hour=d2.time().hour();
|
|
if (hour<12)
|
|
date=date.addDays(-1);
|
|
//date=date.addDays(1);
|
|
} else {
|
|
date=date.addDays(-1);
|
|
|
|
const int hours_since_last_session=4;
|
|
const int hours_since_midnight=12;
|
|
|
|
bool previous=false;
|
|
// Find what day session belongs to.
|
|
if (day.find(date)!=day.end()) {
|
|
// Previous day record exists...
|
|
|
|
// Calculate time since end of previous days last session
|
|
span=(s->first() - day[date]->last())/3600000.0;
|
|
|
|
// less than n hours since last session yesterday?
|
|
if (span < hours_since_last_session) {
|
|
previous=true;
|
|
}
|
|
}
|
|
|
|
if (!previous) {
|
|
// Calculate Hours since midnight.
|
|
d1=d2;
|
|
d1.setTime(QTime(0,0,0));
|
|
float secsto=d1.secsTo(d2);
|
|
span=secsto/3600.0;
|
|
|
|
// Bedtime was late last night.
|
|
if (span < hours_since_midnight) {
|
|
|
|
previous=true;
|
|
}
|
|
}
|
|
|
|
if (!previous) {
|
|
// Revert to sessions original day.
|
|
date=date.addDays(1);
|
|
}
|
|
}
|
|
sessionlist[s->session()]=s;
|
|
|
|
if (!firstsession) {
|
|
if (firstday>date) firstday=date;
|
|
if (lastday<date) lastday=date;
|
|
} else {
|
|
firstday=lastday=date;
|
|
firstsession=false;
|
|
}
|
|
|
|
if (day.find(date)==day.end()) {
|
|
//QString dstr=date.toString("yyyyMMdd");
|
|
//qDebug("Adding Profile Day %s",dstr.toAscii().data());
|
|
day[date]=new Day(this);
|
|
// 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,day[date],m_type);
|
|
}
|
|
day[date]->AddSession(s);
|
|
|
|
return day[date];
|
|
}
|
|
|
|
// 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;
|
|
|
|
|
|
qDebug() << "Purging " << QDir::toNativeSeparators(path);
|
|
|
|
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);
|
|
bool ok;
|
|
ext_s.toInt(&ok,10);
|
|
if (ok) {
|
|
qDebug() << "Deleting " << fullpath;
|
|
dir.remove(fullpath);
|
|
} else could_not_kill++;
|
|
|
|
}
|
|
if (could_not_kill>0) {
|
|
qWarning() << "Could not purge path\n" << path << "\n\n" << could_not_kill << " file(s) remain.. Suggest manually deleting this path\n";
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
bool Machine::Load()
|
|
{
|
|
QString path=profile->Get("DataFolder")+"/"+hexid();
|
|
QDir dir(path);
|
|
qDebug() << "Loading " << path;
|
|
|
|
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;
|
|
QHash<SessionID,StringList> sessfiles;
|
|
QHash<SessionID,StringList>::iterator s;
|
|
|
|
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();
|
|
}
|
|
|
|
int size=sessfiles.size();
|
|
int cnt=0;
|
|
for (s=sessfiles.begin(); s!=sessfiles.end(); s++) {
|
|
cnt++;
|
|
if ((cnt % 10)==0)
|
|
if (qprogress) qprogress->setValue((float(cnt)/float(size)*100.0));
|
|
|
|
Session *sess=new Session(this,s.key());
|
|
|
|
if (sess->LoadSummary(s.value()[0])) {
|
|
sess->SetEventFile(s.value()[1]);
|
|
AddSession(sess,profile);
|
|
} else {
|
|
qWarning() << "Error unpacking summary data";
|
|
delete sess;
|
|
}
|
|
}
|
|
if (qprogress) qprogress->setValue(100);
|
|
return true;
|
|
}
|
|
bool Machine::SaveSession(Session *sess)
|
|
{
|
|
QString path=profile->Get("DataFolder")+"/"+hexid();
|
|
if (sess->IsChanged()) sess->Store(path);
|
|
return true;
|
|
}
|
|
bool Machine::Save()
|
|
{
|
|
QMap<QDate,Day *>::iterator d;
|
|
QVector<Session *>::iterator s;
|
|
int size=0;
|
|
int cnt=0;
|
|
|
|
QString path=profile->Get("DataFolder")+"/"+hexid();
|
|
|
|
// Calculate size for progress bar
|
|
for (d=day.begin();d!=day.end();d++)
|
|
size+=d.value()->size();
|
|
|
|
for (d=day.begin();d!=day.end();d++) {
|
|
|
|
//qDebug() << "Day Save Commenced";
|
|
for (s=d.value()->begin(); s!=d.value()->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();
|
|
|
|
}
|
|
//qDebug() << "Day Save Completed";
|
|
|
|
}
|
|
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()
|
|
{
|
|
}
|
|
|
|
|
|
|
|
|
|
|